diff options
author | Lin Jen-Shin <godfat@godfat.org> | 2017-02-02 11:54:35 +0800 |
---|---|---|
committer | Lin Jen-Shin <godfat@godfat.org> | 2017-02-02 11:54:35 +0800 |
commit | 54fca95160389fe7993df5d82635b83804833fee (patch) | |
tree | 8552f29a7bfbf24af39a5d6a3f8b110c1695f7de /lib | |
parent | eb242fc865c032f6408f3b68700da9b840b416dd (diff) | |
parent | 40a824357c700280f3d2f8e2cda2fabc65af7f69 (diff) | |
download | gitlab-ce-fix-git-hooks-when-creating-file.tar.gz |
Merge remote-tracking branch 'upstream/master' into fix-git-hooks-when-creating-filefix-git-hooks-when-creating-file
* upstream/master: (190 commits)
Remove unnecessary returns / unset variables from the CoffeeScript -> JS conversion.
update spec
Change the reply shortcut to focus the field even without a selection.
use destroy_all
Remove settings cog from within admin scroll tabs; keep links centered
add changelog
remove old project members from project
add spec replicating validation error
Fix small typo on new branch button spec
Improve styling of the new issue message
Don't capitalize environment name in show page
Abillity to promote project labels to group labels
Edited the column header for the environments list from created to updated and added created to environments detail page colum header titles
Update and pin the `jwt` gem to ~> 1.5.6
refactor merge request build service
Update index.md
Clarify that Auto Deploy requires a public project.
19164 Add settings dropdown to mobile screens
cop for gem fetched from a git source
Add CHANGELOG entry
...
Diffstat (limited to 'lib')
44 files changed, 553 insertions, 218 deletions
diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 9f59939e9ae..a07b2a9ca0f 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -137,6 +137,7 @@ module API expose :avatar_url expose :web_url expose :request_access_enabled + expose :full_name, :full_path expose :statistics, if: :statistics do with_options format_with: -> (value) { value.to_i } do diff --git a/lib/api/services.rb b/lib/api/services.rb index a0abec49438..1456fe4688b 100644 --- a/lib/api/services.rb +++ b/lib/api/services.rb @@ -661,6 +661,14 @@ module API end trigger_services.each do |service_slug, settings| + helpers do + def chat_command_service(project, service_slug, params) + project.services.active.where(template: false).find do |service| + service.try(:token) == params[:token] && service.to_param == service_slug.underscore + end + end + end + params do requires :id, type: String, desc: 'The ID of a project' end @@ -679,9 +687,8 @@ module API # This is not accurate, but done to prevent leakage of the project names not_found!('Service') unless project - service = project.find_or_initialize_service(service_slug.underscore) - - result = service.try(:active?) && service.try(:trigger, params) + service = chat_command_service(project, service_slug, params) + result = service.try(:trigger, params) if result status result[:status] || 200 diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb index 8dda65c71ef..f638905a1e0 100644 --- a/lib/gitlab/auth.rb +++ b/lib/gitlab/auth.rb @@ -10,13 +10,16 @@ module Gitlab def find_for_git_client(login, password, project:, ip:) raise "Must provide an IP for rate limiting" if ip.nil? + # `user_with_password_for_git` should be the last check + # because it's the most expensive, especially when LDAP + # is enabled. result = service_request_check(login, password, project) || build_access_token_check(login, password) || - user_with_password_for_git(login, password) || - oauth_access_token_check(login, password) || lfs_token_check(login, password) || + oauth_access_token_check(login, password) || personal_access_token_check(login, password) || + user_with_password_for_git(login, password) || Gitlab::Auth::Result.new rate_limit!(ip, success: result.success?, login: login) @@ -143,7 +146,9 @@ module Gitlab read_authentication_abilities end - Result.new(actor, nil, token_handler.type, authentication_abilities) if Devise.secure_compare(token_handler.token, password) + if Devise.secure_compare(token_handler.token, password) + Gitlab::Auth::Result.new(actor, nil, token_handler.type, authentication_abilities) + end end def build_access_token_check(login, password) diff --git a/lib/gitlab/chat_commands/base_command.rb b/lib/gitlab/chat_commands/base_command.rb index 4fe53ce93a9..25da8474e95 100644 --- a/lib/gitlab/chat_commands/base_command.rb +++ b/lib/gitlab/chat_commands/base_command.rb @@ -42,10 +42,6 @@ module Gitlab def find_by_iid(iid) collection.find_by(iid: iid) end - - def presenter - Gitlab::ChatCommands::Presenter.new - end end end end diff --git a/lib/gitlab/chat_commands/command.rb b/lib/gitlab/chat_commands/command.rb index 145086755e4..f34ed0f4cf2 100644 --- a/lib/gitlab/chat_commands/command.rb +++ b/lib/gitlab/chat_commands/command.rb @@ -3,7 +3,7 @@ module Gitlab class Command < BaseCommand COMMANDS = [ Gitlab::ChatCommands::IssueShow, - Gitlab::ChatCommands::IssueCreate, + Gitlab::ChatCommands::IssueNew, Gitlab::ChatCommands::IssueSearch, Gitlab::ChatCommands::Deploy, ].freeze @@ -13,51 +13,32 @@ module Gitlab if command if command.allowed?(project, current_user) - present command.new(project, current_user, params).execute(match) + command.new(project, current_user, params).execute(match) else - access_denied + Gitlab::ChatCommands::Presenters::Access.new.access_denied end else - help(help_messages) + Gitlab::ChatCommands::Help.new(project, current_user, params).execute(available_commands, params[:text]) end end def match_command match = nil - service = available_commands.find do |klass| - match = klass.match(command) - end + service = + available_commands.find do |klass| + match = klass.match(params[:text]) + end [service, match] end private - def help_messages - available_commands.map(&:help_message) - end - def available_commands COMMANDS.select do |klass| klass.available?(project) end end - - def command - params[:text] - end - - def help(messages) - presenter.help(messages, params[:command]) - end - - def access_denied - presenter.access_denied - end - - def present(resource) - presenter.present(resource) - end end end end diff --git a/lib/gitlab/chat_commands/deploy.rb b/lib/gitlab/chat_commands/deploy.rb index 7127d2f6d04..458d90f84e8 100644 --- a/lib/gitlab/chat_commands/deploy.rb +++ b/lib/gitlab/chat_commands/deploy.rb @@ -1,8 +1,6 @@ module Gitlab module ChatCommands class Deploy < BaseCommand - include Gitlab::Routing.url_helpers - def self.match(text) /\Adeploy\s+(?<from>\S+.*)\s+to+\s+(?<to>\S+.*)\z/.match(text) end @@ -24,35 +22,29 @@ module Gitlab to = match[:to] actions = find_actions(from, to) - return unless actions.present? - if actions.one? - play!(from, to, actions.first) + if actions.none? + Gitlab::ChatCommands::Presenters::Deploy.new(nil).no_actions + elsif actions.one? + action = play!(from, to, actions.first) + Gitlab::ChatCommands::Presenters::Deploy.new(action).present(from, to) else - Result.new(:error, 'Too many actions defined') + Gitlab::ChatCommands::Presenters::Deploy.new(actions).too_many_actions end end private def play!(from, to, action) - new_action = action.play(current_user) - - Result.new(:success, "Deployment from #{from} to #{to} started. Follow the progress: #{url(new_action)}.") + action.play(current_user) end def find_actions(from, to) environment = project.environments.find_by(name: from) - return unless environment + return [] unless environment environment.actions_for(to).select(&:starts_environment?) end - - def url(subject) - polymorphic_url( - [subject.project.namespace.becomes(Namespace), subject.project, subject] - ) - end end end end diff --git a/lib/gitlab/chat_commands/help.rb b/lib/gitlab/chat_commands/help.rb new file mode 100644 index 00000000000..6c0e4d304a4 --- /dev/null +++ b/lib/gitlab/chat_commands/help.rb @@ -0,0 +1,28 @@ +module Gitlab + module ChatCommands + class Help < BaseCommand + # This class has to be used last, as it always matches. It has to match + # because other commands were not triggered and we want to show the help + # command + def self.match(_text) + true + end + + def self.help_message + 'help' + end + + def self.allowed?(_project, _user) + true + end + + def execute(commands, text) + Gitlab::ChatCommands::Presenters::Help.new(commands).present(trigger, text) + end + + def trigger + params[:command] + end + end + end +end diff --git a/lib/gitlab/chat_commands/issue_create.rb b/lib/gitlab/chat_commands/issue_new.rb index cefb6775db8..016054ecd46 100644 --- a/lib/gitlab/chat_commands/issue_create.rb +++ b/lib/gitlab/chat_commands/issue_new.rb @@ -1,8 +1,8 @@ module Gitlab module ChatCommands - class IssueCreate < IssueCommand + class IssueNew < IssueCommand def self.match(text) - # we can not match \n with the dot by passing the m modifier as than + # we can not match \n with the dot by passing the m modifier as than # the title and description are not seperated /\Aissue\s+(new|create)\s+(?<title>[^\n]*)\n*(?<description>(.|\n)*)/.match(text) end @@ -19,8 +19,24 @@ module Gitlab title = match[:title] description = match[:description].to_s.rstrip + issue = create_issue(title: title, description: description) + + if issue.persisted? + presenter(issue).present + else + presenter(issue).display_errors + end + end + + private + + def create_issue(title:, description:) Issues::CreateService.new(project, current_user, title: title, description: description).execute end + + def presenter(issue) + Gitlab::ChatCommands::Presenters::IssueNew.new(issue) + end end end end diff --git a/lib/gitlab/chat_commands/issue_search.rb b/lib/gitlab/chat_commands/issue_search.rb index 51bf80c800b..3491b53093e 100644 --- a/lib/gitlab/chat_commands/issue_search.rb +++ b/lib/gitlab/chat_commands/issue_search.rb @@ -10,7 +10,13 @@ module Gitlab end def execute(match) - collection.search(match[:query]).limit(QUERY_LIMIT) + issues = collection.search(match[:query]).limit(QUERY_LIMIT) + + if issues.present? + Presenters::IssueSearch.new(issues).present + else + Presenters::Access.new(issues).not_found + end end end end diff --git a/lib/gitlab/chat_commands/issue_show.rb b/lib/gitlab/chat_commands/issue_show.rb index 2a45d49cf6b..d6013f4d10c 100644 --- a/lib/gitlab/chat_commands/issue_show.rb +++ b/lib/gitlab/chat_commands/issue_show.rb @@ -10,7 +10,13 @@ module Gitlab end def execute(match) - find_by_iid(match[:iid]) + issue = find_by_iid(match[:iid]) + + if issue + Gitlab::ChatCommands::Presenters::IssueShow.new(issue).present + else + Gitlab::ChatCommands::Presenters::Access.new.not_found + end end end end diff --git a/lib/gitlab/chat_commands/presenter.rb b/lib/gitlab/chat_commands/presenter.rb deleted file mode 100644 index 8930a21f406..00000000000 --- a/lib/gitlab/chat_commands/presenter.rb +++ /dev/null @@ -1,131 +0,0 @@ -module Gitlab - module ChatCommands - class Presenter - include Gitlab::Routing - - def authorize_chat_name(url) - message = if url - ":wave: Hi there! Before I do anything for you, please [connect your GitLab account](#{url})." - else - ":sweat_smile: Couldn't identify you, nor can I autorize you!" - end - - ephemeral_response(message) - end - - def help(commands, trigger) - if commands.none? - ephemeral_response("No commands configured") - else - commands.map! { |command| "#{trigger} #{command}" } - message = header_with_list("Available commands", commands) - - ephemeral_response(message) - end - end - - def present(subject) - return not_found unless subject - - if subject.is_a?(Gitlab::ChatCommands::Result) - show_result(subject) - elsif subject.respond_to?(:count) - if subject.none? - not_found - elsif subject.one? - single_resource(subject.first) - else - multiple_resources(subject) - end - else - single_resource(subject) - end - end - - def access_denied - ephemeral_response("Whoops! That action is not allowed. This incident will be [reported](https://xkcd.com/838/).") - end - - private - - def show_result(result) - case result.type - when :success - in_channel_response(result.message) - else - ephemeral_response(result.message) - end - end - - def not_found - ephemeral_response("404 not found! GitLab couldn't find what you were looking for! :boom:") - end - - def single_resource(resource) - return error(resource) if resource.errors.any? || !resource.persisted? - - message = "#{title(resource)}:" - message << "\n\n#{resource.description}" if resource.try(:description) - - in_channel_response(message) - end - - def multiple_resources(resources) - titles = resources.map { |resource| title(resource) } - - message = header_with_list("Multiple results were found:", titles) - - ephemeral_response(message) - end - - def error(resource) - message = header_with_list("The action was not successful, because:", resource.errors.messages) - - ephemeral_response(message) - end - - def title(resource) - reference = resource.try(:to_reference) || resource.try(:id) - title = resource.try(:title) || resource.try(:name) - - "[#{reference} #{title}](#{url(resource)})" - end - - def header_with_list(header, items) - message = [header] - - items.each do |item| - message << "- #{item}" - end - - message.join("\n") - end - - def url(resource) - url_for( - [ - resource.project.namespace.becomes(Namespace), - resource.project, - resource - ] - ) - end - - def ephemeral_response(message) - { - response_type: :ephemeral, - text: message, - status: 200 - } - end - - def in_channel_response(message) - { - response_type: :in_channel, - text: message, - status: 200 - } - end - end - end -end diff --git a/lib/gitlab/chat_commands/presenters/access.rb b/lib/gitlab/chat_commands/presenters/access.rb new file mode 100644 index 00000000000..92f4fa17f78 --- /dev/null +++ b/lib/gitlab/chat_commands/presenters/access.rb @@ -0,0 +1,40 @@ +module Gitlab + module ChatCommands + module Presenters + class Access < Presenters::Base + def access_denied + ephemeral_response(text: "Whoops! This action is not allowed. This incident will be [reported](https://xkcd.com/838/).") + end + + def not_found + ephemeral_response(text: "404 not found! GitLab couldn't find what you were looking for! :boom:") + end + + def authorize + message = + if @resource + ":wave: Hi there! Before I do anything for you, please [connect your GitLab account](#{@resource})." + else + ":sweat_smile: Couldn't identify you, nor can I autorize you!" + end + + ephemeral_response(text: message) + end + + def unknown_command(commands) + ephemeral_response(text: help_message(trigger)) + end + + private + + def help_message(trigger) + header_with_list("Command not found, these are the commands you can use", full_commands(trigger)) + end + + def full_commands(trigger) + @resource.map { |command| "#{trigger} #{command.help_message}" } + end + end + end + end +end diff --git a/lib/gitlab/chat_commands/presenters/base.rb b/lib/gitlab/chat_commands/presenters/base.rb new file mode 100644 index 00000000000..2700a5a2ad5 --- /dev/null +++ b/lib/gitlab/chat_commands/presenters/base.rb @@ -0,0 +1,77 @@ +module Gitlab + module ChatCommands + module Presenters + class Base + include Gitlab::Routing.url_helpers + + def initialize(resource = nil) + @resource = resource + end + + def display_errors + message = header_with_list("The action was not successful, because:", @resource.errors.full_messages) + + ephemeral_response(text: message) + end + + private + + def header_with_list(header, items) + message = [header] + + items.each do |item| + message << "- #{item}" + end + + message.join("\n") + end + + def ephemeral_response(message) + response = { + response_type: :ephemeral, + status: 200 + }.merge(message) + + format_response(response) + end + + def in_channel_response(message) + response = { + response_type: :in_channel, + status: 200 + }.merge(message) + + format_response(response) + end + + def format_response(response) + response[:text] = format(response[:text]) if response.has_key?(:text) + + if response.has_key?(:attachments) + response[:attachments].each do |attachment| + attachment[:pretext] = format(attachment[:pretext]) if attachment[:pretext] + attachment[:text] = format(attachment[:text]) if attachment[:text] + end + end + + response + end + + # Convert Markdown to slacks format + def format(string) + Slack::Notifier::LinkFormatter.format(string) + end + + def resource_url + url_for( + [ + @resource.project.namespace.becomes(Namespace), + @resource.project, + @resource + ] + ) + end + end + end + end +end diff --git a/lib/gitlab/chat_commands/presenters/deploy.rb b/lib/gitlab/chat_commands/presenters/deploy.rb new file mode 100644 index 00000000000..863d0bf99ca --- /dev/null +++ b/lib/gitlab/chat_commands/presenters/deploy.rb @@ -0,0 +1,21 @@ +module Gitlab + module ChatCommands + module Presenters + class Deploy < Presenters::Base + def present(from, to) + message = "Deployment started from #{from} to #{to}. [Follow its progress](#{resource_url})." + + in_channel_response(text: message) + end + + def no_actions + ephemeral_response(text: "No action found to be executed") + end + + def too_many_actions + ephemeral_response(text: "Too many actions defined") + end + end + end + end +end diff --git a/lib/gitlab/chat_commands/presenters/help.rb b/lib/gitlab/chat_commands/presenters/help.rb new file mode 100644 index 00000000000..cd47b7f4c6a --- /dev/null +++ b/lib/gitlab/chat_commands/presenters/help.rb @@ -0,0 +1,27 @@ +module Gitlab + module ChatCommands + module Presenters + class Help < Presenters::Base + def present(trigger, text) + ephemeral_response(text: help_message(trigger, text)) + end + + private + + def help_message(trigger, text) + return "No commands available :thinking_face:" unless @resource.present? + + if text.start_with?('help') + header_with_list("Available commands", full_commands(trigger)) + else + header_with_list("Unknown command, these commands are available", full_commands(trigger)) + end + end + + def full_commands(trigger) + @resource.map { |command| "#{trigger} #{command.help_message}" } + end + end + end + end +end diff --git a/lib/gitlab/chat_commands/presenters/issuable.rb b/lib/gitlab/chat_commands/presenters/issuable.rb new file mode 100644 index 00000000000..dfb1c8f6616 --- /dev/null +++ b/lib/gitlab/chat_commands/presenters/issuable.rb @@ -0,0 +1,43 @@ +module Gitlab + module ChatCommands + module Presenters + module Issuable + def color(issuable) + issuable.open? ? '#38ae67' : '#d22852' + end + + def status_text(issuable) + issuable.open? ? 'Open' : 'Closed' + end + + def project + @resource.project + end + + def author + @resource.author + end + + def fields + [ + { + title: "Assignee", + value: @resource.assignee ? @resource.assignee.name : "_None_", + short: true + }, + { + title: "Milestone", + value: @resource.milestone ? @resource.milestone.title : "_None_", + short: true + }, + { + title: "Labels", + value: @resource.labels.any? ? @resource.label_names : "_None_", + short: true + } + ] + end + end + end + end +end diff --git a/lib/gitlab/chat_commands/presenters/issue_new.rb b/lib/gitlab/chat_commands/presenters/issue_new.rb new file mode 100644 index 00000000000..a1a3add56c9 --- /dev/null +++ b/lib/gitlab/chat_commands/presenters/issue_new.rb @@ -0,0 +1,50 @@ +module Gitlab + module ChatCommands + module Presenters + class IssueNew < Presenters::Base + include Presenters::Issuable + + def present + in_channel_response(new_issue) + end + + private + + def new_issue + { + attachments: [ + { + title: "#{@resource.title} · #{@resource.to_reference}", + title_link: resource_url, + author_name: author.name, + author_icon: author.avatar_url, + fallback: "New issue #{@resource.to_reference}: #{@resource.title}", + pretext: pretext, + color: color(@resource), + fields: fields, + mrkdwn_in: [ + :title, + :pretext, + :text, + :fields + ] + } + ] + } + end + + def pretext + "I created an issue on #{author_profile_link}'s behalf: **#{@resource.to_reference}** in #{project_link}" + end + + def project_link + "[#{project.name_with_namespace}](#{projects_url(project)})" + end + + def author_profile_link + "[#{author.to_reference}](#{url_for(author)})" + end + end + end + end +end diff --git a/lib/gitlab/chat_commands/presenters/issue_search.rb b/lib/gitlab/chat_commands/presenters/issue_search.rb new file mode 100644 index 00000000000..3478359b91d --- /dev/null +++ b/lib/gitlab/chat_commands/presenters/issue_search.rb @@ -0,0 +1,47 @@ +module Gitlab + module ChatCommands + module Presenters + class IssueSearch < Presenters::Base + include Presenters::Issuable + + def present + text = if @resource.count >= 5 + "Here are the first 5 issues I found:" + elsif @resource.one? + "Here is the only issue I found:" + else + "Here are the #{@resource.count} issues I found:" + end + + ephemeral_response(text: text, attachments: attachments) + end + + private + + def attachments + @resource.map do |issue| + url = "[#{issue.to_reference}](#{url_for([namespace, project, issue])})" + + { + color: color(issue), + fallback: "#{issue.to_reference} #{issue.title}", + text: "#{url} · #{issue.title} (#{status_text(issue)})", + + mrkdwn_in: [ + :text + ] + } + end + end + + def project + @project ||= @resource.first.project + end + + def namespace + @namespace ||= project.namespace.becomes(Namespace) + end + end + end + end +end diff --git a/lib/gitlab/chat_commands/presenters/issue_show.rb b/lib/gitlab/chat_commands/presenters/issue_show.rb new file mode 100644 index 00000000000..fe5847ccd15 --- /dev/null +++ b/lib/gitlab/chat_commands/presenters/issue_show.rb @@ -0,0 +1,61 @@ +module Gitlab + module ChatCommands + module Presenters + class IssueShow < Presenters::Base + include Presenters::Issuable + + def present + if @resource.confidential? + ephemeral_response(show_issue) + else + in_channel_response(show_issue) + end + end + + private + + def show_issue + { + attachments: [ + { + title: "#{@resource.title} · #{@resource.to_reference}", + title_link: resource_url, + author_name: author.name, + author_icon: author.avatar_url, + fallback: "Issue #{@resource.to_reference}: #{@resource.title}", + pretext: pretext, + text: text, + color: color(@resource), + fields: fields, + mrkdwn_in: [ + :pretext, + :text, + :fields + ] + } + ] + } + end + + def text + message = "**#{status_text(@resource)}**" + + if @resource.upvotes.zero? && @resource.downvotes.zero? && @resource.user_notes_count.zero? + return message + end + + message << " · " + message << ":+1: #{@resource.upvotes} " unless @resource.upvotes.zero? + message << ":-1: #{@resource.downvotes} " unless @resource.downvotes.zero? + message << ":speech_balloon: #{@resource.user_notes_count}" unless @resource.user_notes_count.zero? + + message + end + + def pretext + "Issue *#{@resource.to_reference}* from #{project.name_with_namespace}" + end + end + end + end +end diff --git a/lib/gitlab/ci/status/build/cancelable.rb b/lib/gitlab/ci/status/build/cancelable.rb index a979fe7d573..67bbc3c4849 100644 --- a/lib/gitlab/ci/status/build/cancelable.rb +++ b/lib/gitlab/ci/status/build/cancelable.rb @@ -10,7 +10,7 @@ module Gitlab end def action_icon - 'ban' + 'icon_action_cancel' end def action_path diff --git a/lib/gitlab/ci/status/build/play.rb b/lib/gitlab/ci/status/build/play.rb index 1bf949c96dd..0f4b7b24cef 100644 --- a/lib/gitlab/ci/status/build/play.rb +++ b/lib/gitlab/ci/status/build/play.rb @@ -26,17 +26,13 @@ module Gitlab end def action_icon - 'play' + 'icon_action_play' end def action_title 'Play' end - def action_class - 'ci-play-icon' - end - def action_path play_namespace_project_build_path(subject.project.namespace, subject.project, diff --git a/lib/gitlab/ci/status/build/retryable.rb b/lib/gitlab/ci/status/build/retryable.rb index 8e38d6a8523..6b362af7634 100644 --- a/lib/gitlab/ci/status/build/retryable.rb +++ b/lib/gitlab/ci/status/build/retryable.rb @@ -10,7 +10,7 @@ module Gitlab end def action_icon - 'refresh' + 'icon_action_retry' end def action_title diff --git a/lib/gitlab/ci/status/build/stop.rb b/lib/gitlab/ci/status/build/stop.rb index e1dfdb76d41..90401cad0d2 100644 --- a/lib/gitlab/ci/status/build/stop.rb +++ b/lib/gitlab/ci/status/build/stop.rb @@ -26,7 +26,7 @@ module Gitlab end def action_icon - 'stop' + 'icon_action_stop' end def action_title diff --git a/lib/gitlab/ci/status/core.rb b/lib/gitlab/ci/status/core.rb index 73b6ab5a635..3dd2b9e01f6 100644 --- a/lib/gitlab/ci/status/core.rb +++ b/lib/gitlab/ci/status/core.rb @@ -42,9 +42,6 @@ module Gitlab raise NotImplementedError end - def action_class - end - def action_path raise NotImplementedError end diff --git a/lib/gitlab/ci/trace_reader.rb b/lib/gitlab/ci/trace_reader.rb index 37e51536e8f..1d7ddeb3e0f 100644 --- a/lib/gitlab/ci/trace_reader.rb +++ b/lib/gitlab/ci/trace_reader.rb @@ -42,6 +42,7 @@ module Gitlab end chunks.join.lines.last(max_lines).join + .force_encoding(Encoding.default_external) end end end diff --git a/lib/gitlab/current_settings.rb b/lib/gitlab/current_settings.rb index 4ebd48a3fc7..e20f5f6f514 100644 --- a/lib/gitlab/current_settings.rb +++ b/lib/gitlab/current_settings.rb @@ -30,7 +30,7 @@ module Gitlab end def in_memory_application_settings - @in_memory_application_settings ||= ::ApplicationSetting.new(::ApplicationSetting::DEFAULTS) + @in_memory_application_settings ||= ::ApplicationSetting.new(::ApplicationSetting.defaults) # In case migrations the application_settings table is not created yet, # we fallback to a simple OpenStruct rescue ActiveRecord::StatementInvalid, ActiveRecord::UnknownAttributeError @@ -38,7 +38,7 @@ module Gitlab end def fake_application_settings - OpenStruct.new(::ApplicationSetting::DEFAULTS) + OpenStruct.new(::ApplicationSetting.defaults) end private diff --git a/lib/gitlab/cycle_analytics/base_stage.rb b/lib/gitlab/cycle_analytics/base_stage.rb index 74bbcdcb3dd..559e3939da6 100644 --- a/lib/gitlab/cycle_analytics/base_stage.rb +++ b/lib/gitlab/cycle_analytics/base_stage.rb @@ -13,7 +13,7 @@ module Gitlab end def as_json - AnalyticsStageSerializer.new.represent(self).as_json + AnalyticsStageSerializer.new.represent(self) end def title diff --git a/lib/gitlab/cycle_analytics/code_event_fetcher.rb b/lib/gitlab/cycle_analytics/code_event_fetcher.rb index 5245b9ca8fc..d5bf6149749 100644 --- a/lib/gitlab/cycle_analytics/code_event_fetcher.rb +++ b/lib/gitlab/cycle_analytics/code_event_fetcher.rb @@ -18,7 +18,7 @@ module Gitlab private def serialize(event) - AnalyticsMergeRequestSerializer.new(project: @project).represent(event).as_json + AnalyticsMergeRequestSerializer.new(project: @project).represent(event) end end end diff --git a/lib/gitlab/cycle_analytics/issue_event_fetcher.rb b/lib/gitlab/cycle_analytics/issue_event_fetcher.rb index 0d8da99455e..3df9cbdcfce 100644 --- a/lib/gitlab/cycle_analytics/issue_event_fetcher.rb +++ b/lib/gitlab/cycle_analytics/issue_event_fetcher.rb @@ -16,7 +16,7 @@ module Gitlab private def serialize(event) - AnalyticsIssueSerializer.new(project: @project).represent(event).as_json + AnalyticsIssueSerializer.new(project: @project).represent(event) end end end diff --git a/lib/gitlab/cycle_analytics/plan_event_fetcher.rb b/lib/gitlab/cycle_analytics/plan_event_fetcher.rb index 88a8710dbe6..7d342a2d2cb 100644 --- a/lib/gitlab/cycle_analytics/plan_event_fetcher.rb +++ b/lib/gitlab/cycle_analytics/plan_event_fetcher.rb @@ -37,7 +37,7 @@ module Gitlab def serialize_commit(event, st_commit, query) commit = Commit.new(Gitlab::Git::Commit.new(st_commit), @project) - AnalyticsCommitSerializer.new(project: @project, total_time: event['total_time']).represent(commit).as_json + AnalyticsCommitSerializer.new(project: @project, total_time: event['total_time']).represent(commit) end end end diff --git a/lib/gitlab/cycle_analytics/review_event_fetcher.rb b/lib/gitlab/cycle_analytics/review_event_fetcher.rb index 4df0bd06393..4c7b3f4467f 100644 --- a/lib/gitlab/cycle_analytics/review_event_fetcher.rb +++ b/lib/gitlab/cycle_analytics/review_event_fetcher.rb @@ -15,7 +15,7 @@ module Gitlab end def serialize(event) - AnalyticsMergeRequestSerializer.new(project: @project).represent(event).as_json + AnalyticsMergeRequestSerializer.new(project: @project).represent(event) end end end diff --git a/lib/gitlab/cycle_analytics/stage_summary.rb b/lib/gitlab/cycle_analytics/stage_summary.rb index b34baf5b081..fc77bd86097 100644 --- a/lib/gitlab/cycle_analytics/stage_summary.rb +++ b/lib/gitlab/cycle_analytics/stage_summary.rb @@ -16,7 +16,7 @@ module Gitlab private def serialize(summary_object) - AnalyticsSummarySerializer.new.represent(summary_object).as_json + AnalyticsSummarySerializer.new.represent(summary_object) end end end diff --git a/lib/gitlab/cycle_analytics/staging_event_fetcher.rb b/lib/gitlab/cycle_analytics/staging_event_fetcher.rb index a34731a5fcd..36c0260dbfe 100644 --- a/lib/gitlab/cycle_analytics/staging_event_fetcher.rb +++ b/lib/gitlab/cycle_analytics/staging_event_fetcher.rb @@ -23,7 +23,7 @@ module Gitlab private def serialize(event) - AnalyticsBuildSerializer.new.represent(event['build']).as_json + AnalyticsBuildSerializer.new.represent(event['build']) end end end diff --git a/lib/gitlab/import_export.rb b/lib/gitlab/import_export.rb index eb667a85b78..d679edec36b 100644 --- a/lib/gitlab/import_export.rb +++ b/lib/gitlab/import_export.rb @@ -3,7 +3,7 @@ module Gitlab extend self # For every version update, the version history in import_export.md has to be kept up to date. - VERSION = '0.1.5' + VERSION = '0.1.6' FILENAME_LIMIT = 50 def export_path(relative_path:) diff --git a/lib/gitlab/import_export/import_export.yml b/lib/gitlab/import_export/import_export.yml index 08ad3274b38..416194e57d7 100644 --- a/lib/gitlab/import_export/import_export.yml +++ b/lib/gitlab/import_export/import_export.yml @@ -39,7 +39,6 @@ project_tree: - :author - :events - :statuses - - :variables - :triggers - :deploy_keys - :services diff --git a/lib/gitlab/import_export/members_mapper.rb b/lib/gitlab/import_export/members_mapper.rb index 2405b94db50..a09577ae48d 100644 --- a/lib/gitlab/import_export/members_mapper.rb +++ b/lib/gitlab/import_export/members_mapper.rb @@ -41,6 +41,8 @@ module Gitlab end def ensure_default_member! + @project.project_members.destroy_all + ProjectMember.create!(user: @user, access_level: ProjectMember::MASTER, source_id: @project.id, importing: true) end diff --git a/lib/gitlab/import_export/relation_factory.rb b/lib/gitlab/import_export/relation_factory.rb index 19e43cce768..0319d7707a8 100644 --- a/lib/gitlab/import_export/relation_factory.rb +++ b/lib/gitlab/import_export/relation_factory.rb @@ -4,7 +4,6 @@ module Gitlab OVERRIDES = { snippets: :project_snippets, pipelines: 'Ci::Pipeline', statuses: 'commit_status', - variables: 'Ci::Variable', triggers: 'Ci::Trigger', builds: 'Ci::Build', hooks: 'ProjectHook', @@ -24,6 +23,8 @@ module Gitlab EXISTING_OBJECT_CHECK = %i[milestone milestones label labels project_label project_labels group_label group_labels].freeze + TOKEN_RESET_MODELS = %w[Ci::Trigger Ci::Build ProjectHook].freeze + def self.create(*args) new(*args).create end @@ -61,7 +62,9 @@ module Gitlab update_project_references handle_group_label if group_label? - reset_ci_tokens if @relation_name == 'Ci::Trigger' + reset_tokens! + remove_encrypted_attributes! + @relation_hash['data'].deep_symbolize_keys! if @relation_name == :events && @relation_hash['data'] set_st_diffs if @relation_name == :merge_request_diff end @@ -140,11 +143,22 @@ module Gitlab end end - def reset_ci_tokens - return unless Gitlab::ImportExport.reset_tokens? + def reset_tokens! + return unless Gitlab::ImportExport.reset_tokens? && TOKEN_RESET_MODELS.include?(@relation_name.to_s) # If we import/export a project to the same instance, tokens will have to be reset. - @relation_hash['token'] = nil + # We also have to reset them to avoid issues when the gitlab secrets file cannot be copied across. + relation_class.attribute_names.select { |name| name.include?('token') }.each do |token| + @relation_hash[token] = nil + end + end + + def remove_encrypted_attributes! + return unless relation_class.respond_to?(:encrypted_attributes) && relation_class.encrypted_attributes.any? + + relation_class.encrypted_attributes.each_key do |key| + @relation_hash[key.to_s] = nil + end end def relation_class diff --git a/lib/gitlab/backend/shell.rb b/lib/gitlab/shell.rb index 82e194c1af1..82e194c1af1 100644 --- a/lib/gitlab/backend/shell.rb +++ b/lib/gitlab/shell.rb diff --git a/lib/gitlab/backend/shell_adapter.rb b/lib/gitlab/shell_adapter.rb index fbe2a7a0d72..fbe2a7a0d72 100644 --- a/lib/gitlab/backend/shell_adapter.rb +++ b/lib/gitlab/shell_adapter.rb diff --git a/lib/gitlab/upgrader.rb b/lib/gitlab/upgrader.rb index f3567f3ef85..e78d0c34a02 100644 --- a/lib/gitlab/upgrader.rb +++ b/lib/gitlab/upgrader.rb @@ -61,7 +61,7 @@ module Gitlab "Switch to new version" => %W(#{Gitlab.config.git.bin_path} checkout v#{latest_version}), "Install gems" => %W(bundle), "Migrate DB" => %W(bundle exec rake db:migrate), - "Recompile assets" => %W(bundle exec rake assets:clean assets:precompile), + "Recompile assets" => %W(bundle exec rake gitlab:assets:clean gitlab:assets:compile), "Clear cache" => %W(bundle exec rake cache:clear) } end diff --git a/lib/gitlab/view/presenter/base.rb b/lib/gitlab/view/presenter/base.rb index 83c8ba5c1cf..dbfe0941e4d 100644 --- a/lib/gitlab/view/presenter/base.rb +++ b/lib/gitlab/view/presenter/base.rb @@ -1,6 +1,8 @@ module Gitlab module View module Presenter + CannotOverrideMethodError = Class.new(StandardError) + module Base extend ActiveSupport::Concern diff --git a/lib/gitlab/view/presenter/delegated.rb b/lib/gitlab/view/presenter/delegated.rb index f4d330c590e..387ff0f5d43 100644 --- a/lib/gitlab/view/presenter/delegated.rb +++ b/lib/gitlab/view/presenter/delegated.rb @@ -8,6 +8,10 @@ module Gitlab @subject = subject attributes.each do |key, value| + if subject.respond_to?(key) + raise CannotOverrideMethodError.new("#{subject} already respond to #{key}!") + end + define_singleton_method(key) { value } end diff --git a/lib/support/deploy/deploy.sh b/lib/support/deploy/deploy.sh index adea4c7a747..ab46c47d8f5 100755 --- a/lib/support/deploy/deploy.sh +++ b/lib/support/deploy/deploy.sh @@ -31,8 +31,8 @@ echo 'Deploy: Bundle and migrate' sudo -u git -H bundle --without aws development test mysql --deployment sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production -sudo -u git -H bundle exec rake assets:clean RAILS_ENV=production -sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production +sudo -u git -H bundle exec rake gitlab:assets:clean RAILS_ENV=production +sudo -u git -H bundle exec rake gitlab:assets:compile RAILS_ENV=production sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production # return stashed changes (if necessary) diff --git a/lib/tasks/gitlab/assets.rake b/lib/tasks/gitlab/assets.rake new file mode 100644 index 00000000000..5d884bf9f66 --- /dev/null +++ b/lib/tasks/gitlab/assets.rake @@ -0,0 +1,47 @@ +namespace :gitlab do + namespace :assets do + desc 'GitLab | Assets | Compile all frontend assets' + task :compile do + Rake::Task['assets:precompile'].invoke + Rake::Task['gitlab:assets:fix_urls'].invoke + end + + desc 'GitLab | Assets | Clean up old compiled frontend assets' + task :clean do + Rake::Task['assets:clean'].invoke + end + + desc 'GitLab | Assets | Remove all compiled frontend assets' + task :purge do + Rake::Task['assets:clobber'].invoke + end + + desc 'GitLab | Assets | Fix all absolute url references in CSS' + task :fix_urls do + css_files = Dir['public/assets/*.css'] + css_files.each do | file | + # replace url(/assets/*) with url(./*) + puts "Fixing #{file}" + system "sed", "-i", "-e", 's/url(\([\"\']\?\)\/assets\//url(\1.\//g', file + + # rewrite the corresponding gzip file (if it exists) + gzip = "#{file}.gz" + if File.exist?(gzip) + puts "Fixing #{gzip}" + + FileUtils.rm(gzip) + mtime = File.stat(file).mtime + + File.open(gzip, 'wb+') do |f| + gz = Zlib::GzipWriter.new(f, Zlib::BEST_COMPRESSION) + gz.mtime = mtime + gz.write IO.binread(file) + gz.close + + File.utime(mtime, mtime, f.path) + end + end + end + end + end +end |