diff options
19 files changed, 167 insertions, 35 deletions
diff --git a/Gemfile.rails5.lock b/Gemfile.rails5.lock index f9ec29cde90..63b450d3f62 100644 --- a/Gemfile.rails5.lock +++ b/Gemfile.rails5.lock @@ -126,7 +126,7 @@ GEM numerizer (~> 0.1.1) chunky_png (1.3.5) citrus (3.0.2) - coderay (1.1.1) + coderay (1.1.2) coercible (1.0.0) descendants_tracker (~> 0.0.1) commonmarker (0.17.8) @@ -495,7 +495,7 @@ GEM memoist (0.16.0) memoizable (0.4.2) thread_safe (~> 0.3, >= 0.3.1) - method_source (0.8.2) + method_source (0.9.0) mime-types (3.1) mime-types-data (~> 3.2015) mime-types-data (3.2016.0521) @@ -638,12 +638,11 @@ GEM unparser procto (0.0.3) prometheus-client-mmap (0.9.4) - pry (0.10.4) + pry (0.11.3) coderay (~> 1.1.0) - method_source (~> 0.8.1) - slop (~> 3.4) - pry-byebug (3.4.2) - byebug (~> 9.0) + method_source (~> 0.9.0) + pry-byebug (3.4.3) + byebug (>= 9.0, < 9.1) pry (~> 0.10) pry-rails (0.3.5) pry (>= 0.9.10) @@ -751,7 +750,7 @@ GEM retriable (3.1.2) rinku (2.0.0) rotp (2.1.2) - rouge (3.2.0) + rouge (3.2.1) rqrcode (0.7.0) chunky_png rqrcode-rails3 (0.1.7) @@ -817,7 +816,7 @@ GEM rubyzip (1.2.1) rufus-scheduler (3.4.0) et-orbi (~> 1.0) - rugged (0.27.2) + rugged (0.27.4) safe_yaml (1.0.4) sanitize (4.6.6) crass (~> 1.0.2) @@ -878,7 +877,6 @@ GEM simplecov-html (~> 0.10.0) simplecov-html (0.10.0) slack-notifier (1.5.1) - slop (3.6.0) spring (2.0.1) activesupport (>= 4.2) spring-commands-rspec (1.0.4) diff --git a/app/assets/javascripts/vue_shared/components/stacked_progress_bar.vue b/app/assets/javascripts/vue_shared/components/stacked_progress_bar.vue index f44d361c47e..78fde463507 100644 --- a/app/assets/javascripts/vue_shared/components/stacked_progress_bar.vue +++ b/app/assets/javascripts/vue_shared/components/stacked_progress_bar.vue @@ -71,7 +71,11 @@ export default { }, methods: { getPercent(count) { - return roundOffFloat((count / this.totalCount) * 100, 1); + const percent = roundOffFloat((count / this.totalCount) * 100, 1); + if (percent > 0 && percent < 1) { + return '< 1'; + } + return percent; }, barStyle(percent) { return `width: ${percent}%;`; diff --git a/app/helpers/import_helper.rb b/app/helpers/import_helper.rb index 4664b1728c4..c65f1565425 100644 --- a/app/helpers/import_helper.rb +++ b/app/helpers/import_helper.rb @@ -5,6 +5,10 @@ module ImportHelper false end + def sanitize_project_name(name) + name.gsub(/[^\w\-]/, '-') + end + def import_project_target(owner, name) namespace = current_user.can_create_group? ? owner : current_user.namespace_path "#{namespace}/#{name}" diff --git a/app/services/merge_requests/build_service.rb b/app/services/merge_requests/build_service.rb index bc988eb2a26..55750269bb4 100644 --- a/app/services/merge_requests/build_service.rb +++ b/app/services/merge_requests/build_service.rb @@ -128,8 +128,7 @@ module MergeRequests # def assign_title_and_description assign_title_and_description_from_single_commit - assign_title_from_issue if target_project.issues_enabled? || target_project.external_issue_tracker - + merge_request.title ||= title_from_issue if target_project.issues_enabled? || target_project.external_issue_tracker merge_request.title ||= source_branch.titleize.humanize merge_request.title = wip_title if compare_commits.empty? @@ -159,20 +158,18 @@ module MergeRequests merge_request.description ||= commit.description.try(:strip) end - def assign_title_from_issue + def title_from_issue return unless issue - merge_request.title = "Resolve \"#{issue.title}\"" if issue.is_a?(Issue) + return "Resolve \"#{issue.title}\"" if issue.is_a?(Issue) - return if merge_request.title.present? + return if issue_iid.blank? - if issue_iid.present? - title_parts = ["Resolve #{issue.to_reference}"] - branch_title = source_branch.downcase.remove(issue_iid.downcase).titleize.humanize + title_parts = ["Resolve #{issue.to_reference}"] + branch_title = source_branch.downcase.remove(issue_iid.downcase).titleize.humanize - title_parts << "\"#{branch_title}\"" if branch_title.present? - merge_request.title = title_parts.join(' ') - end + title_parts << "\"#{branch_title}\"" if branch_title.present? + title_parts.join(' ') end def issue_iid diff --git a/app/views/import/_githubish_status.html.haml b/app/views/import/_githubish_status.html.haml index f0d1e837317..f4a29ed18dc 100644 --- a/app/views/import/_githubish_status.html.haml +++ b/app/views/import/_githubish_status.html.haml @@ -45,7 +45,7 @@ = text_field_tag :path, current_user.namespace_path, class: "input-group-text input-large form-control", tabindex: 1, disabled: true %span.input-group-prepend .input-group-text / - = text_field_tag :path, repo.name, class: "input-mini form-control", tabindex: 2, autofocus: true, required: true + = text_field_tag :path, sanitize_project_name(repo.name), class: "input-mini form-control", tabindex: 2, autofocus: true, required: true %td.import-actions.job-status = button_tag class: "btn btn-import js-add-to-import" do = has_ci_cd_only_params? ? _('Connect') : _('Import') diff --git a/app/views/import/bitbucket/status.html.haml b/app/views/import/bitbucket/status.html.haml index a75b7aa9dd2..3b1b5e55302 100644 --- a/app/views/import/bitbucket/status.html.haml +++ b/app/views/import/bitbucket/status.html.haml @@ -63,7 +63,7 @@ = text_field_tag :path, current_user.namespace_path, class: "input-group-text input-large form-control", tabindex: 1, disabled: true %span.input-group-prepend .input-group-text / - = text_field_tag :path, repo.name, class: "input-mini form-control", tabindex: 2, autofocus: true, required: true + = text_field_tag :path, sanitize_project_name(repo.slug), class: "input-mini form-control", tabindex: 2, autofocus: true, required: true %td.import-actions.job-status = button_tag class: 'btn btn-import js-add-to-import' do = _('Import') diff --git a/app/views/import/bitbucket_server/status.html.haml b/app/views/import/bitbucket_server/status.html.haml index 3d05a5e696f..ae09e0dfa18 100644 --- a/app/views/import/bitbucket_server/status.html.haml +++ b/app/views/import/bitbucket_server/status.html.haml @@ -61,7 +61,7 @@ = text_field_tag :path, current_user.namespace_path, class: "input-group-text input-large form-control", tabindex: 1, disabled: true %span.input-group-prepend .input-group-text / - = text_field_tag :path, repo.name, class: "input-mini form-control", tabindex: 2, autofocus: true, required: true + = text_field_tag :path, sanitize_project_name(repo.slug), class: "input-mini form-control", tabindex: 2, autofocus: true, required: true %td.import-actions.job-status = button_tag class: 'btn btn-import js-add-to-import' do Import diff --git a/changelogs/unreleased/6028-show-generic-percent-stacked-progress-bar.yml b/changelogs/unreleased/6028-show-generic-percent-stacked-progress-bar.yml new file mode 100644 index 00000000000..94098dd0144 --- /dev/null +++ b/changelogs/unreleased/6028-show-generic-percent-stacked-progress-bar.yml @@ -0,0 +1,6 @@ +--- +title: Show '< 1%' when percent value evaluated is less than 1 on Stacked Progress + Bar +merge_request: 21306 +author: +type: fixed diff --git a/changelogs/unreleased/fix-mr-title-fallback-logic.yml b/changelogs/unreleased/fix-mr-title-fallback-logic.yml new file mode 100644 index 00000000000..5056c38573b --- /dev/null +++ b/changelogs/unreleased/fix-mr-title-fallback-logic.yml @@ -0,0 +1,5 @@ +--- +title: Fix fallback logic for automatic MR title assignment +merge_request: 20930 +author: Franz Liedke +type: fixed diff --git a/changelogs/unreleased/rails5-update-gemfile-lock.yml b/changelogs/unreleased/rails5-update-gemfile-lock.yml new file mode 100644 index 00000000000..3891b16e2b8 --- /dev/null +++ b/changelogs/unreleased/rails5-update-gemfile-lock.yml @@ -0,0 +1,5 @@ +--- +title: Rails5 update Gemfile.rails5.lock +merge_request: 21388 +author: Jasper Maes +type: other diff --git a/changelogs/unreleased/sh-insert-git-data-in-separate-transaction.yml b/changelogs/unreleased/sh-insert-git-data-in-separate-transaction.yml new file mode 100644 index 00000000000..116929b2f53 --- /dev/null +++ b/changelogs/unreleased/sh-insert-git-data-in-separate-transaction.yml @@ -0,0 +1,5 @@ +--- +title: 'Bitbucket Server importer: Eliminate most idle-in-transaction issues' +merge_request: +author: +type: performance diff --git a/changelogs/unreleased/sh-sanitize-project-import-names.yml b/changelogs/unreleased/sh-sanitize-project-import-names.yml new file mode 100644 index 00000000000..6e0284bda08 --- /dev/null +++ b/changelogs/unreleased/sh-sanitize-project-import-names.yml @@ -0,0 +1,5 @@ +--- +title: Use slugs for default project path and sanitize names before import +merge_request: 21367 +author: +type: fixed diff --git a/lib/gitlab/bitbucket_server_import/importer.rb b/lib/gitlab/bitbucket_server_import/importer.rb index 268d21a77d1..b591d94668f 100644 --- a/lib/gitlab/bitbucket_server_import/importer.rb +++ b/lib/gitlab/bitbucket_server_import/importer.rb @@ -1,7 +1,10 @@ +# frozen_string_literal: true + module Gitlab module BitbucketServerImport class Importer include Gitlab::ShellAdapter + attr_reader :recover_missing_commits attr_reader :project, :project_key, :repository_slug, :client, :errors, :users @@ -175,21 +178,18 @@ module Gitlab description = '' description += @formatter.author_line(pull_request.author) unless find_user_id(pull_request.author_email) description += pull_request.description if pull_request.description - - source_branch_sha = pull_request.source_branch_sha - target_branch_sha = pull_request.target_branch_sha author_id = gitlab_user_id(pull_request.author_email) attributes = { iid: pull_request.iid, title: pull_request.title, description: description, - source_project: project, + source_project_id: project.id, source_branch: Gitlab::Git.ref_name(pull_request.source_branch_name), - source_branch_sha: source_branch_sha, - target_project: project, + source_branch_sha: pull_request.source_branch_sha, + target_project_id: project.id, target_branch: Gitlab::Git.ref_name(pull_request.target_branch_name), - target_branch_sha: target_branch_sha, + target_branch_sha: pull_request.target_branch_sha, state: pull_request.state, author_id: author_id, assignee_id: nil, @@ -197,7 +197,9 @@ module Gitlab updated_at: pull_request.updated_at } - merge_request = project.merge_requests.create!(attributes) + creator = Gitlab::Import::MergeRequestCreator.new(project) + merge_request = creator.execute(attributes) + import_pull_request_comments(pull_request, merge_request) if merge_request.persisted? end diff --git a/lib/gitlab/import/merge_request_creator.rb b/lib/gitlab/import/merge_request_creator.rb new file mode 100644 index 00000000000..a01951b0762 --- /dev/null +++ b/lib/gitlab/import/merge_request_creator.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +# This module is designed for importers that need to create many merge +# requests quickly. When creating merge requests there are a lot of hooks +# that may run, for many different reasons. Many of these hooks (e.g. the ones +# used for rendering Markdown) are completely unnecessary and may even lead to +# transaction timeouts. +# +# To ensure importing merge requests requests has a minimal impact and can +# complete in a reasonable time we bypass all the hooks by inserting the row +# and then retrieving it. We then only perform the additional work that is +# strictly necessary. +module Gitlab + module Import + class MergeRequestCreator + include ::Gitlab::Import::DatabaseHelpers + include ::Gitlab::Import::MergeRequestHelpers + + attr_accessor :project + + def initialize(project) + @project = project + end + + def execute(attributes) + source_branch_sha = attributes.delete(:source_branch_sha) + target_branch_sha = attributes.delete(:target_branch_sha) + iid = attributes[:iid] + + merge_request, already_exists = create_merge_request_without_hooks(project, attributes, iid) + + if merge_request + insert_or_replace_git_data(merge_request, source_branch_sha, target_branch_sha, already_exists) + end + + merge_request + end + end + end +end diff --git a/qa/qa/page/project/import/github.rb b/qa/qa/page/project/import/github.rb index 36567927194..1a410a0f8a5 100644 --- a/qa/qa/page/project/import/github.rb +++ b/qa/qa/page/project/import/github.rb @@ -14,7 +14,7 @@ module QA element :project_import_row, 'data: { qa: { repo_path: repo.full_name } }' element :project_namespace_select element :project_namespace_field, 'select_tag :namespace_id' - element :project_path_field, 'text_field_tag :path, repo.name' + element :project_path_field, 'text_field_tag :path, sanitize_project_name(repo.name)' element :import_button, "_('Import')" end diff --git a/spec/helpers/import_helper_spec.rb b/spec/helpers/import_helper_spec.rb index 033155617c6..cb0ea4e26ba 100644 --- a/spec/helpers/import_helper_spec.rb +++ b/spec/helpers/import_helper_spec.rb @@ -1,6 +1,16 @@ require 'rails_helper' describe ImportHelper do + describe '#sanitize_project_name' do + it 'removes whitespace' do + expect(helper.sanitize_project_name('my test repo')).to eq('my-test-repo') + end + + it 'removes disallowed characters' do + expect(helper.sanitize_project_name('Test&me$over*h_ere')).to eq('Test-me-over-h_ere') + end + end + describe '#import_project_target' do let(:user) { create(:user) } diff --git a/spec/javascripts/vue_shared/components/stacked_progress_bar_spec.js b/spec/javascripts/vue_shared/components/stacked_progress_bar_spec.js index 076d940961d..f1fe2e996fc 100644 --- a/spec/javascripts/vue_shared/components/stacked_progress_bar_spec.js +++ b/spec/javascripts/vue_shared/components/stacked_progress_bar_spec.js @@ -44,7 +44,11 @@ describe('StackedProgressBarComponent', () => { }); it('returns percentage with decimal place from provided count based on `totalCount`', () => { - expect(vm.getPercent(10)).toBe(0.2); + expect(vm.getPercent(67)).toBe(1.3); + }); + + it('returns percentage as `< 1` from provided count based on `totalCount` when evaluated value is less than 1', () => { + expect(vm.getPercent(10)).toBe('< 1'); }); }); diff --git a/spec/lib/gitlab/import/merge_request_creator_spec.rb b/spec/lib/gitlab/import/merge_request_creator_spec.rb new file mode 100644 index 00000000000..cd3359da341 --- /dev/null +++ b/spec/lib/gitlab/import/merge_request_creator_spec.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Gitlab::Import::MergeRequestCreator do + let(:project) { create(:project, :repository) } + + subject { described_class.new(project) } + + describe '#execute' do + context 'merge request already exists' do + let(:merge_request) { create(:merge_request, target_project: project, source_project: project) } + let(:commits) { merge_request.merge_request_diffs.first.commits } + let(:attributes) { HashWithIndifferentAccess.new(merge_request.attributes) } + + it 'updates the data' do + commits_count = commits.count + merge_request.merge_request_diffs.destroy_all # rubocop: disable DestroyAll + + expect(merge_request.merge_request_diffs.count).to eq(0) + + subject.execute(attributes) + + expect(merge_request.reload.merge_request_diffs.count).to eq(1) + expect(merge_request.reload.merge_request_diffs.first.commits.count).to eq(commits_count) + end + end + + context 'new merge request' do + let(:merge_request) { build(:merge_request, target_project: project, source_project: project) } + let(:attributes) { HashWithIndifferentAccess.new(merge_request.attributes) } + + it 'creates a new merge request' do + attributes.delete(:id) + + expect { subject.execute(attributes) }.to change { MergeRequest.count }.by(1) + + new_mr = MergeRequest.last + expect(new_mr.merge_request_diffs.count).to eq(1) + end + end + end +end diff --git a/spec/services/merge_requests/build_service_spec.rb b/spec/services/merge_requests/build_service_spec.rb index 6aed481939e..0ced5d1b6d6 100644 --- a/spec/services/merge_requests/build_service_spec.rb +++ b/spec/services/merge_requests/build_service_spec.rb @@ -169,6 +169,10 @@ describe MergeRequests::BuildService do end end + it 'uses the title of the commit as the title of the merge request' do + expect(merge_request.title).to eq('Initial commit') + end + it 'appends the closing description' do expected_description = [commit_description, closing_message].compact.join("\n\n") |