From d3de5fcfa8331e13bcf00d41653c2c6ee337abf5 Mon Sep 17 00:00:00 2001 From: Bastian Blank Date: Sat, 30 Mar 2019 00:27:10 +0100 Subject: Always show instance configuration link The link to the useful instance configuration page was hidden behind the commercial content setting. Just display it always. --- app/views/help/index.html.haml | 5 +++-- changelogs/unreleased/always-link-instance-configuration.yml | 5 +++++ 2 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 changelogs/unreleased/always-link-instance-configuration.yml diff --git a/app/views/help/index.html.haml b/app/views/help/index.html.haml index f40fdb0b86b..916f98a62d1 100644 --- a/app/views/help/index.html.haml +++ b/app/views/help/index.html.haml @@ -24,8 +24,9 @@ Used by more than 100,000 organizations, GitLab is the most popular solution to manage git repositories on-premises. %br Read more about GitLab at #{link_to promo_host, promo_url, target: '_blank', rel: 'noopener noreferrer'}. - %p= link_to 'Check the current instance configuration ', help_instance_configuration_url - %hr + +%p= link_to 'Check the current instance configuration ', help_instance_configuration_url +%hr .row.prepend-top-default .col-md-8 diff --git a/changelogs/unreleased/always-link-instance-configuration.yml b/changelogs/unreleased/always-link-instance-configuration.yml new file mode 100644 index 00000000000..3f08747edf7 --- /dev/null +++ b/changelogs/unreleased/always-link-instance-configuration.yml @@ -0,0 +1,5 @@ +--- +title: Always show instance configuration link +merge_request: 26783 +author: Bastian Blank +type: fixed -- cgit v1.2.1 From f8fdb59059b8c1037fd804636e4247642a08ebb9 Mon Sep 17 00:00:00 2001 From: Joan Queralt Date: Wed, 3 Apr 2019 07:59:46 +0000 Subject: public key -> private key --- doc/user/project/pages/lets_encrypt_for_gitlab_pages.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/user/project/pages/lets_encrypt_for_gitlab_pages.md b/doc/user/project/pages/lets_encrypt_for_gitlab_pages.md index f639188684b..5ad500c4d20 100644 --- a/doc/user/project/pages/lets_encrypt_for_gitlab_pages.md +++ b/doc/user/project/pages/lets_encrypt_for_gitlab_pages.md @@ -134,7 +134,7 @@ Now that your certificate has been issued, let's add it to your Pages site: sudo cat /etc/letsencrypt/live/example.com/fullchain.pem | pbcopy ``` -1. Copy and paste the public key into the second field **Key (PEM)**: +1. Copy and paste the private key into the second field **Key (PEM)**: ```bash sudo cat /etc/letsencrypt/live/example.com/privkey.pem | pbcopy -- cgit v1.2.1 From 29a68cc5bc0583b61457dedc78529f97491558f0 Mon Sep 17 00:00:00 2001 From: Vasiliy Ermolovich Date: Wed, 3 Apr 2019 23:59:14 +0300 Subject: Use Rack::Utils.clean_path_info instead of copy-pasted version. --- app/controllers/help_controller.rb | 33 +-------------------------------- 1 file changed, 1 insertion(+), 32 deletions(-) diff --git a/app/controllers/help_controller.rb b/app/controllers/help_controller.rb index a9d6addd4a4..10cdce98437 100644 --- a/app/controllers/help_controller.rb +++ b/app/controllers/help_controller.rb @@ -22,7 +22,7 @@ class HelpController < ApplicationController end def show - @path = clean_path_info(path_params[:path]) + @path = Rack::Utils.clean_path_info(path_params[:path]) respond_to do |format| format.any(:markdown, :md, :html) do @@ -75,35 +75,4 @@ class HelpController < ApplicationController params end - - PATH_SEPS = Regexp.union(*[::File::SEPARATOR, ::File::ALT_SEPARATOR].compact) - - # Taken from ActionDispatch::FileHandler - # Cleans up the path, to prevent directory traversal outside the doc folder. - def clean_path_info(path_info) - parts = path_info.split(PATH_SEPS) - - clean = [] - - # Walk over each part of the path - parts.each do |part| - # Turn `one//two` or `one/./two` into `one/two`. - next if part.empty? || part == '.' - - if part == '..' - # Turn `one/two/../` into `one` - clean.pop - else - # Add simple folder names to the clean path. - clean << part - end - end - - # If the path was an absolute path (i.e. `/` or `/one/two`), - # add `/` to the front of the clean path. - clean.unshift '/' if parts.empty? || parts.first.empty? - - # Join all the clean path parts by the path separator. - ::File.join(*clean) - end end -- cgit v1.2.1 From 0adedbb4822a8daaa215b33c88ace136c31d042d Mon Sep 17 00:00:00 2001 From: Hiroyuki Sato Date: Mon, 1 Apr 2019 15:11:08 +0900 Subject: Fix the bug that the project statistics is not updated --- app/workers/all_queues.yml | 1 + app/workers/project_cache_worker.rb | 14 ++++--- app/workers/update_project_statistics_worker.rb | 22 ++++++++++ changelogs/unreleased/delay-update-statictics.yml | 5 +++ config/sidekiq_queues.yml | 3 +- spec/workers/project_cache_worker_spec.rb | 36 +++++++++------- .../update_project_statistics_worker_spec.rb | 48 ++++++++++++++++++++++ 7 files changed, 107 insertions(+), 22 deletions(-) create mode 100644 app/workers/update_project_statistics_worker.rb create mode 100644 changelogs/unreleased/delay-update-statictics.yml create mode 100644 spec/workers/update_project_statistics_worker_spec.rb diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml index 3e8c2a1209a..f9b2e698fc9 100644 --- a/app/workers/all_queues.yml +++ b/app/workers/all_queues.yml @@ -143,6 +143,7 @@ - repository_remove_remote - system_hook_push - update_merge_requests +- update_project_statistics - upload_checksum - web_hook - repository_update_remote_mirror diff --git a/app/workers/project_cache_worker.rb b/app/workers/project_cache_worker.rb index b31099bc670..73eb461768c 100644 --- a/app/workers/project_cache_worker.rb +++ b/app/workers/project_cache_worker.rb @@ -28,18 +28,20 @@ class ProjectCacheWorker def update_statistics(project, statistics = []) return if Gitlab::Database.read_only? - return unless try_obtain_lease_for(project.id, :update_statistics) + return unless try_obtain_lease_for(project.id, statistics) - Rails.logger.info("Updating statistics for project #{project.id}") - - project.statistics.refresh!(only: statistics) + UpdateProjectStatisticsWorker.perform_in(LEASE_TIMEOUT, project.id, statistics) end private - def try_obtain_lease_for(project_id, section) + def try_obtain_lease_for(project_id, statistics) Gitlab::ExclusiveLease - .new("project_cache_worker:#{project_id}:#{section}", timeout: LEASE_TIMEOUT) + .new(project_cache_worker_key(project_id, statistics), timeout: LEASE_TIMEOUT) .try_obtain end + + def project_cache_worker_key(project_id, statistics) + (["project_cache_worker", project_id] + statistics.sort).join(":") + end end diff --git a/app/workers/update_project_statistics_worker.rb b/app/workers/update_project_statistics_worker.rb new file mode 100644 index 00000000000..46673c4b07e --- /dev/null +++ b/app/workers/update_project_statistics_worker.rb @@ -0,0 +1,22 @@ + +# frozen_string_literal: true + +# Worker for updating project statistics. +class UpdateProjectStatisticsWorker + include ApplicationWorker + + # project_id - The ID of the project for which to flush the cache. + # statistics - An Array containing columns from ProjectStatistics to + # refresh, if empty all columns will be refreshed + # rubocop: disable CodeReuse/ActiveRecord + def perform(project_id, statistics = []) + project = Project.find_by(id: project_id) + + return unless project && project.repository.exists? + + Rails.logger.info("Updating statistics for project #{project.id}") + + project.statistics.refresh!(only: statistics.map(&:to_sym)) + end + # rubocop: enable CodeReuse/ActiveRecord +end diff --git a/changelogs/unreleased/delay-update-statictics.yml b/changelogs/unreleased/delay-update-statictics.yml new file mode 100644 index 00000000000..d0201fb6db8 --- /dev/null +++ b/changelogs/unreleased/delay-update-statictics.yml @@ -0,0 +1,5 @@ +--- +title: Fix the bug that the project statistics is not updated +merge_request: 26854 +author: Hiroyuki Sato +type: fixed diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml index 2dc0da00919..8bc2426ec4c 100644 --- a/config/sidekiq_queues.yml +++ b/config/sidekiq_queues.yml @@ -89,4 +89,5 @@ - [project_daily_statistics, 1] - [import_issues_csv, 2] - [chat_notification, 2] - - [migrate_external_diffs, 1] + - [migrate_external_diffs, 1] + - [update_project_statistics, 1] diff --git a/spec/workers/project_cache_worker_spec.rb b/spec/workers/project_cache_worker_spec.rb index a7353227043..724947228b7 100644 --- a/spec/workers/project_cache_worker_spec.rb +++ b/spec/workers/project_cache_worker_spec.rb @@ -7,9 +7,9 @@ describe ProjectCacheWorker do let(:worker) { described_class.new } let(:project) { create(:project, :repository) } - let(:statistics) { project.statistics } - let(:lease_key) { "project_cache_worker:#{project.id}:update_statistics" } + let(:lease_key) { (["project_cache_worker", project.id] + statistics.sort).join(":") } let(:lease_timeout) { ProjectCacheWorker::LEASE_TIMEOUT } + let(:statistics) { [] } describe '#perform' do before do @@ -35,14 +35,6 @@ describe ProjectCacheWorker do end context 'with an existing project' do - it 'updates the project statistics' do - expect(worker).to receive(:update_statistics) - .with(kind_of(Project), %i(repository_size)) - .and_call_original - - worker.perform(project.id, [], %w(repository_size)) - end - it 'refreshes the method caches' do expect_any_instance_of(Repository).to receive(:refresh_method_caches) .with(%i(readme)) @@ -51,6 +43,18 @@ describe ProjectCacheWorker do worker.perform(project.id, %w(readme)) end + context 'with statistics' do + let(:statistics) { %w(repository_size) } + + it 'updates the project statistics' do + expect(worker).to receive(:update_statistics) + .with(kind_of(Project), %i(repository_size)) + .and_call_original + + worker.perform(project.id, [], statistics) + end + end + context 'with plain readme' do it 'refreshes the method caches' do allow(MarkupHelper).to receive(:gitlab_markdown?).and_return(false) @@ -66,13 +70,15 @@ describe ProjectCacheWorker do end describe '#update_statistics' do + let(:statistics) { %w(repository_size) } + context 'when a lease could not be obtained' do it 'does not update the repository size' do stub_exclusive_lease_taken(lease_key, timeout: lease_timeout) - expect(statistics).not_to receive(:refresh!) + expect(UpdateProjectStatisticsWorker).not_to receive(:perform_in) - worker.update_statistics(project) + worker.update_statistics(project, statistics.map(&:to_sym)) end end @@ -80,11 +86,11 @@ describe ProjectCacheWorker do it 'updates the project statistics' do stub_exclusive_lease(lease_key, timeout: lease_timeout) - expect(statistics).to receive(:refresh!) - .with(only: %i(repository_size)) + expect(UpdateProjectStatisticsWorker).to receive(:perform_in) + .with(lease_timeout, project.id, statistics.map(&:to_sym)) .and_call_original - worker.update_statistics(project, %i(repository_size)) + worker.update_statistics(project, statistics.map(&:to_sym)) end end end diff --git a/spec/workers/update_project_statistics_worker_spec.rb b/spec/workers/update_project_statistics_worker_spec.rb new file mode 100644 index 00000000000..3411e10da7e --- /dev/null +++ b/spec/workers/update_project_statistics_worker_spec.rb @@ -0,0 +1,48 @@ +require 'spec_helper' + +describe UpdateProjectStatisticsWorker do + let(:worker) { described_class.new } + let(:project) { create(:project, :repository) } + + describe '#perform' do + context 'with a non-existing project' do + it 'does nothing' do + expect_any_instance_of(ProjectStatistics).not_to receive(:refresh!) + + worker.perform(-1) + end + end + + context 'with an existing project without a repository' do + it 'does nothing' do + allow_any_instance_of(Repository).to receive(:exists?).and_return(false) + + expect_any_instance_of(ProjectStatistics).not_to receive(:refresh!) + + worker.perform(project.id) + end + end + + context 'with an existing project' do + it 'refreshes the project statistics' do + expect_any_instance_of(ProjectStatistics).to receive(:refresh!) + .with(only: []) + .and_call_original + + worker.perform(project.id) + end + + context 'with a specific statistics target' do + it 'refreshes the project repository size' do + statistics_target = %w(repository_size) + + expect_any_instance_of(ProjectStatistics).to receive(:refresh!) + .with(only: statistics_target.map(&:to_sym)) + .and_call_original + + worker.perform(project.id, statistics_target) + end + end + end + end +end -- cgit v1.2.1 From e6780501cbfd0cae31fadd15b2964204171091cc Mon Sep 17 00:00:00 2001 From: Hiroyuki Sato Date: Fri, 5 Apr 2019 00:17:52 +0900 Subject: Refactor project_cache_worker_key --- app/workers/project_cache_worker.rb | 2 +- spec/workers/project_cache_worker_spec.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/workers/project_cache_worker.rb b/app/workers/project_cache_worker.rb index 73eb461768c..2b25b96a6f8 100644 --- a/app/workers/project_cache_worker.rb +++ b/app/workers/project_cache_worker.rb @@ -42,6 +42,6 @@ class ProjectCacheWorker end def project_cache_worker_key(project_id, statistics) - (["project_cache_worker", project_id] + statistics.sort).join(":") + ["project_cache_worker", project_id, *statistics.sort].join(":") end end diff --git a/spec/workers/project_cache_worker_spec.rb b/spec/workers/project_cache_worker_spec.rb index 724947228b7..7053bfc2bfd 100644 --- a/spec/workers/project_cache_worker_spec.rb +++ b/spec/workers/project_cache_worker_spec.rb @@ -7,7 +7,7 @@ describe ProjectCacheWorker do let(:worker) { described_class.new } let(:project) { create(:project, :repository) } - let(:lease_key) { (["project_cache_worker", project.id] + statistics.sort).join(":") } + let(:lease_key) { ["project_cache_worker", project.id, *statistics.sort].join(":") } let(:lease_timeout) { ProjectCacheWorker::LEASE_TIMEOUT } let(:statistics) { [] } -- cgit v1.2.1 From 074a1797fe581c8eb5cc65bd56af584d5c500688 Mon Sep 17 00:00:00 2001 From: Hiroyuki Sato Date: Fri, 5 Apr 2019 00:18:17 +0900 Subject: Update the project statistics immediatelly --- app/workers/project_cache_worker.rb | 7 +++++++ spec/workers/project_cache_worker_spec.rb | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/app/workers/project_cache_worker.rb b/app/workers/project_cache_worker.rb index 2b25b96a6f8..5f4972d8f93 100644 --- a/app/workers/project_cache_worker.rb +++ b/app/workers/project_cache_worker.rb @@ -26,10 +26,17 @@ class ProjectCacheWorker end # rubocop: enable CodeReuse/ActiveRecord + # NOTE: triggering both an immediate update and one in 15 minutes if we + # successfully obtain the lease. That way, we only need to wait for the + # statistics to become accurate if they were already updated once in the + # last 15 minutes. def update_statistics(project, statistics = []) return if Gitlab::Database.read_only? return unless try_obtain_lease_for(project.id, statistics) + Rails.logger.info("Updating statistics for project #{project.id}") + + project.statistics.refresh!(only: statistics) UpdateProjectStatisticsWorker.perform_in(LEASE_TIMEOUT, project.id, statistics) end diff --git a/spec/workers/project_cache_worker_spec.rb b/spec/workers/project_cache_worker_spec.rb index 7053bfc2bfd..d2445f420f8 100644 --- a/spec/workers/project_cache_worker_spec.rb +++ b/spec/workers/project_cache_worker_spec.rb @@ -86,6 +86,10 @@ describe ProjectCacheWorker do it 'updates the project statistics' do stub_exclusive_lease(lease_key, timeout: lease_timeout) + expect(project.statistics).to receive(:refresh!) + .with(only: statistics.map(&:to_sym)) + .and_call_original + expect(UpdateProjectStatisticsWorker).to receive(:perform_in) .with(lease_timeout, project.id, statistics.map(&:to_sym)) .and_call_original -- cgit v1.2.1 From 770f721962cd30e930ab7b6e06e9386da6325c3c Mon Sep 17 00:00:00 2001 From: Hiroyuki Sato Date: Fri, 5 Apr 2019 22:07:09 +0900 Subject: Refactor: extract duplicate steps to a service class --- app/services/projects/update_statistics_service.rb | 19 ++++++++++ app/workers/project_cache_worker.rb | 5 +-- app/workers/update_project_statistics_worker.rb | 6 +-- .../projects/update_statistics_service_spec.rb | 40 ++++++++++++++++++++ spec/workers/project_cache_worker_spec.rb | 19 ++++++---- .../update_project_statistics_worker_spec.rb | 43 +++------------------- 6 files changed, 79 insertions(+), 53 deletions(-) create mode 100644 app/services/projects/update_statistics_service.rb create mode 100644 spec/services/projects/update_statistics_service_spec.rb diff --git a/app/services/projects/update_statistics_service.rb b/app/services/projects/update_statistics_service.rb new file mode 100644 index 00000000000..f32a779fab0 --- /dev/null +++ b/app/services/projects/update_statistics_service.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +module Projects + class UpdateStatisticsService < BaseService + def execute + return unless project && project.repository.exists? + + Rails.logger.info("Updating statistics for project #{project.id}") + + project.statistics.refresh!(only: statistics.map(&:to_sym)) + end + + private + + def statistics + params[:statistics] + end + end +end diff --git a/app/workers/project_cache_worker.rb b/app/workers/project_cache_worker.rb index 5f4972d8f93..b2e0701008a 100644 --- a/app/workers/project_cache_worker.rb +++ b/app/workers/project_cache_worker.rb @@ -18,7 +18,7 @@ class ProjectCacheWorker return unless project && project.repository.exists? - update_statistics(project, statistics.map(&:to_sym)) + update_statistics(project, statistics) project.repository.refresh_method_caches(files.map(&:to_sym)) @@ -34,9 +34,8 @@ class ProjectCacheWorker return if Gitlab::Database.read_only? return unless try_obtain_lease_for(project.id, statistics) - Rails.logger.info("Updating statistics for project #{project.id}") + Projects::UpdateStatisticsService.new(project, nil, statistics: statistics).execute - project.statistics.refresh!(only: statistics) UpdateProjectStatisticsWorker.perform_in(LEASE_TIMEOUT, project.id, statistics) end diff --git a/app/workers/update_project_statistics_worker.rb b/app/workers/update_project_statistics_worker.rb index 46673c4b07e..9a29cc12707 100644 --- a/app/workers/update_project_statistics_worker.rb +++ b/app/workers/update_project_statistics_worker.rb @@ -12,11 +12,7 @@ class UpdateProjectStatisticsWorker def perform(project_id, statistics = []) project = Project.find_by(id: project_id) - return unless project && project.repository.exists? - - Rails.logger.info("Updating statistics for project #{project.id}") - - project.statistics.refresh!(only: statistics.map(&:to_sym)) + Projects::UpdateStatisticsService.new(project, nil, statistics: statistics).execute end # rubocop: enable CodeReuse/ActiveRecord end diff --git a/spec/services/projects/update_statistics_service_spec.rb b/spec/services/projects/update_statistics_service_spec.rb new file mode 100644 index 00000000000..7e351c9ce54 --- /dev/null +++ b/spec/services/projects/update_statistics_service_spec.rb @@ -0,0 +1,40 @@ +require 'spec_helper' + +describe Projects::UpdateStatisticsService do + let(:service) { described_class.new(project, nil, statistics: statistics)} + let(:statistics) { %w(repository_size) } + + describe '#execute' do + context 'with a non-existing project' do + let(:project) { nil } + + it 'does nothing' do + expect_any_instance_of(ProjectStatistics).not_to receive(:refresh!) + + service.execute + end + end + + context 'with an existing project without a repository' do + let(:project) { create(:project) } + + it 'does nothing' do + expect_any_instance_of(ProjectStatistics).not_to receive(:refresh!) + + service.execute + end + end + + context 'with an existing project with a repository' do + let(:project) { create(:project, :repository) } + + it 'refreshes the project statistics' do + expect_any_instance_of(ProjectStatistics).to receive(:refresh!) + .with(only: statistics.map(&:to_sym)) + .and_call_original + + service.execute + end + end + end +end diff --git a/spec/workers/project_cache_worker_spec.rb b/spec/workers/project_cache_worker_spec.rb index d2445f420f8..3c40269adc7 100644 --- a/spec/workers/project_cache_worker_spec.rb +++ b/spec/workers/project_cache_worker_spec.rb @@ -48,7 +48,7 @@ describe ProjectCacheWorker do it 'updates the project statistics' do expect(worker).to receive(:update_statistics) - .with(kind_of(Project), %i(repository_size)) + .with(kind_of(Project), statistics) .and_call_original worker.perform(project.id, [], statistics) @@ -73,28 +73,31 @@ describe ProjectCacheWorker do let(:statistics) { %w(repository_size) } context 'when a lease could not be obtained' do - it 'does not update the repository size' do + it 'does not update the project statistics' do stub_exclusive_lease_taken(lease_key, timeout: lease_timeout) + expect(Projects::UpdateStatisticsService).not_to receive(:new) + expect(UpdateProjectStatisticsWorker).not_to receive(:perform_in) - worker.update_statistics(project, statistics.map(&:to_sym)) + worker.update_statistics(project, statistics) end end context 'when a lease could be obtained' do - it 'updates the project statistics' do + it 'updates the project statistics twice' do stub_exclusive_lease(lease_key, timeout: lease_timeout) - expect(project.statistics).to receive(:refresh!) - .with(only: statistics.map(&:to_sym)) + expect(Projects::UpdateStatisticsService).to receive(:new) + .with(project, nil, statistics: statistics) .and_call_original + .twice expect(UpdateProjectStatisticsWorker).to receive(:perform_in) - .with(lease_timeout, project.id, statistics.map(&:to_sym)) + .with(lease_timeout, project.id, statistics) .and_call_original - worker.update_statistics(project, statistics.map(&:to_sym)) + worker.update_statistics(project, statistics) end end end diff --git a/spec/workers/update_project_statistics_worker_spec.rb b/spec/workers/update_project_statistics_worker_spec.rb index 3411e10da7e..a268fd2e4ba 100644 --- a/spec/workers/update_project_statistics_worker_spec.rb +++ b/spec/workers/update_project_statistics_worker_spec.rb @@ -3,46 +3,15 @@ require 'spec_helper' describe UpdateProjectStatisticsWorker do let(:worker) { described_class.new } let(:project) { create(:project, :repository) } + let(:statistics) { %w(repository_size) } describe '#perform' do - context 'with a non-existing project' do - it 'does nothing' do - expect_any_instance_of(ProjectStatistics).not_to receive(:refresh!) + it 'updates the project statistics' do + expect(Projects::UpdateStatisticsService).to receive(:new) + .with(project, nil, statistics: statistics) + .and_call_original - worker.perform(-1) - end - end - - context 'with an existing project without a repository' do - it 'does nothing' do - allow_any_instance_of(Repository).to receive(:exists?).and_return(false) - - expect_any_instance_of(ProjectStatistics).not_to receive(:refresh!) - - worker.perform(project.id) - end - end - - context 'with an existing project' do - it 'refreshes the project statistics' do - expect_any_instance_of(ProjectStatistics).to receive(:refresh!) - .with(only: []) - .and_call_original - - worker.perform(project.id) - end - - context 'with a specific statistics target' do - it 'refreshes the project repository size' do - statistics_target = %w(repository_size) - - expect_any_instance_of(ProjectStatistics).to receive(:refresh!) - .with(only: statistics_target.map(&:to_sym)) - .and_call_original - - worker.perform(project.id, statistics_target) - end - end + worker.perform(project.id, statistics) end end end -- cgit v1.2.1 From e82ed3f46bcc5442668e64b7080f7bb4425956c0 Mon Sep 17 00:00:00 2001 From: charlieablett Date: Mon, 8 Apr 2019 16:52:40 +1200 Subject: Abstract out method from spec to support --- spec/features/boards/sidebar_spec.rb | 1 + spec/support/helpers/filtered_search_helpers.rb | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/spec/features/boards/sidebar_spec.rb b/spec/features/boards/sidebar_spec.rb index dfdb8d589eb..d036699f226 100644 --- a/spec/features/boards/sidebar_spec.rb +++ b/spec/features/boards/sidebar_spec.rb @@ -129,6 +129,7 @@ describe 'Issue Boards', :js do click_link 'Unassigned' end + close_dropdown_menu_if_visible wait_for_requests expect(page).to have_content('No assignee') diff --git a/spec/support/helpers/filtered_search_helpers.rb b/spec/support/helpers/filtered_search_helpers.rb index 6569feec39b..03057a102c5 100644 --- a/spec/support/helpers/filtered_search_helpers.rb +++ b/spec/support/helpers/filtered_search_helpers.rb @@ -149,4 +149,10 @@ module FilteredSearchHelpers loop until find('.filtered-search').value.strip == text end end + + def close_dropdown_menu_if_visible + find('.dropdown-menu-toggle', visible: :all).tap do |toggle| + toggle.click if toggle.visible? + end + end end -- cgit v1.2.1 From e0efa97c7f24bc5816ecdcb6a633150e7a6a43f6 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Wed, 3 Apr 2019 18:33:52 +0700 Subject: Prevent triggering pipelines when target branch is updated Currently, pipelines for merge requests are triggered when source or target branch is updated. However, we should create only when source branch is updated, because it runs unexpected pipelines. --- app/services/merge_requests/refresh_service.rb | 10 +++++-- ...nt-running-mr-pipelines-when-target-updated.yml | 5 ++++ .../merge_requests/refresh_service_spec.rb | 34 +++++++++++++++++----- 3 files changed, 40 insertions(+), 9 deletions(-) create mode 100644 changelogs/unreleased/prevent-running-mr-pipelines-when-target-updated.yml diff --git a/app/services/merge_requests/refresh_service.rb b/app/services/merge_requests/refresh_service.rb index 51d27673787..e0460f7081c 100644 --- a/app/services/merge_requests/refresh_service.rb +++ b/app/services/merge_requests/refresh_service.rb @@ -21,6 +21,7 @@ module MergeRequests post_merge_manually_merged reload_merge_requests outdate_suggestions + refresh_pipelines_on_merge_requests reset_merge_when_pipeline_succeeds mark_pending_todos_done cache_merge_requests_closing_issues @@ -107,8 +108,6 @@ module MergeRequests end merge_request.mark_as_unchecked - create_pipeline_for(merge_request, current_user) - UpdateHeadPipelineForMergeRequestWorker.perform_async(merge_request.id) end # Upcoming method calls need the refreshed version of @@ -134,6 +133,13 @@ module MergeRequests end end + def refresh_pipelines_on_merge_requests + merge_requests_for_source_branch.each do |merge_request| + create_pipeline_for(merge_request, current_user) + UpdateHeadPipelineForMergeRequestWorker.perform_async(merge_request.id) + end + end + def reset_merge_when_pipeline_succeeds merge_requests_for_source_branch.each(&:reset_merge_when_pipeline_succeeds) end diff --git a/changelogs/unreleased/prevent-running-mr-pipelines-when-target-updated.yml b/changelogs/unreleased/prevent-running-mr-pipelines-when-target-updated.yml new file mode 100644 index 00000000000..d003ca55feb --- /dev/null +++ b/changelogs/unreleased/prevent-running-mr-pipelines-when-target-updated.yml @@ -0,0 +1,5 @@ +--- +title: Create pipelines for merge requests only when source branch is updated +merge_request: 26921 +author: +type: fixed diff --git a/spec/services/merge_requests/refresh_service_spec.rb b/spec/services/merge_requests/refresh_service_spec.rb index bd10523bc94..5ed06df7072 100644 --- a/spec/services/merge_requests/refresh_service_spec.rb +++ b/spec/services/merge_requests/refresh_service_spec.rb @@ -146,7 +146,10 @@ describe MergeRequests::RefreshService do stub_ci_pipeline_yaml_file(YAML.dump(config)) end - subject { service.new(@project, @user).execute(@oldrev, @newrev, 'refs/heads/master') } + subject { service.new(project, @user).execute(@oldrev, @newrev, ref) } + + let(:ref) { 'refs/heads/master' } + let(:project) { @project } context "when .gitlab-ci.yml has merge_requests keywords" do let(:config) do @@ -162,14 +165,17 @@ describe MergeRequests::RefreshService do it 'create detached merge request pipeline with commits' do expect { subject } .to change { @merge_request.merge_request_pipelines.count }.by(1) - .and change { @fork_merge_request.merge_request_pipelines.count }.by(1) .and change { @another_merge_request.merge_request_pipelines.count }.by(0) expect(@merge_request.has_commits?).to be_truthy - expect(@fork_merge_request.has_commits?).to be_truthy expect(@another_merge_request.has_commits?).to be_falsy end + it 'does not create detached merge request pipeline for forked project' do + expect { subject } + .not_to change { @fork_merge_request.merge_request_pipelines.count } + end + it 'create detached merge request pipeline for non-fork merge request' do subject @@ -177,11 +183,25 @@ describe MergeRequests::RefreshService do .to be_detached_merge_request_pipeline end - it 'create legacy detached merge request pipeline for fork merge request' do - subject + context 'when service is hooked by target branch' do + let(:ref) { 'refs/heads/feature' } - expect(@fork_merge_request.merge_request_pipelines.first) - .to be_legacy_detached_merge_request_pipeline + it 'does not create detached merge request pipeline' do + expect { subject } + .not_to change { @merge_request.merge_request_pipelines.count } + end + end + + context 'when service runs on forked project' do + let(:project) { @fork_project } + + it 'creates legacy detached merge request pipeline for fork merge request' do + expect { subject } + .to change { @fork_merge_request.merge_request_pipelines.count }.by(1) + + expect(@fork_merge_request.merge_request_pipelines.first) + .to be_legacy_detached_merge_request_pipeline + end end context 'when ci_use_merge_request_ref feature flag is false' do -- cgit v1.2.1 From 4e95aa3de59220d32211f608f66400a1f067d77a Mon Sep 17 00:00:00 2001 From: charlieablett Date: Mon, 8 Apr 2019 19:38:34 +1200 Subject: Add helper reference --- spec/features/boards/sidebar_spec.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/features/boards/sidebar_spec.rb b/spec/features/boards/sidebar_spec.rb index d036699f226..b358c6b9c34 100644 --- a/spec/features/boards/sidebar_spec.rb +++ b/spec/features/boards/sidebar_spec.rb @@ -2,6 +2,7 @@ require 'rails_helper' describe 'Issue Boards', :js do include BoardHelpers + include FilteredSearchHelpers let(:user) { create(:user) } let(:user2) { create(:user) } -- cgit v1.2.1 From 8fdfd521b27e6332ee8bd55d5beecea2cbae9ce0 Mon Sep 17 00:00:00 2001 From: Alexandru Croitor Date: Wed, 3 Apr 2019 14:23:58 +0300 Subject: Extract due quick action to shared example --- .../issues/user_uses_quick_actions_spec.rb | 29 +--------------- .../issue/due_quick_action_shared_examples.rb | 40 ++++++++++++++-------- 2 files changed, 26 insertions(+), 43 deletions(-) diff --git a/spec/features/issues/user_uses_quick_actions_spec.rb b/spec/features/issues/user_uses_quick_actions_spec.rb index ea474759547..68af8303c2f 100644 --- a/spec/features/issues/user_uses_quick_actions_spec.rb +++ b/spec/features/issues/user_uses_quick_actions_spec.rb @@ -60,34 +60,7 @@ describe 'Issues > User uses quick actions', :js do it_behaves_like 'remove_due_date quick action' it_behaves_like 'duplicate quick action' it_behaves_like 'create_merge_request quick action' - - describe 'adding a due date from note' do - let(:issue) { create(:issue, project: project) } - - it_behaves_like 'due quick action available and date can be added' - - context 'when the current user cannot update the due date' do - let(:guest) { create(:user) } - before do - project.add_guest(guest) - gitlab_sign_out - sign_in(guest) - visit project_issue_path(project, issue) - end - - it_behaves_like 'due quick action not available' - end - end - - describe 'toggling the WIP prefix from the title from note' do - let(:issue) { create(:issue, project: project) } - - it 'does not recognize the command nor create a note' do - add_note("/wip") - - expect(page).not_to have_content '/wip' - end - end + it_behaves_like 'due quick action' describe 'move the issue to another project' do let(:issue) { create(:issue, project: project) } diff --git a/spec/support/shared_examples/quick_actions/issue/due_quick_action_shared_examples.rb b/spec/support/shared_examples/quick_actions/issue/due_quick_action_shared_examples.rb index db3ecccc339..ae78cd86cd5 100644 --- a/spec/support/shared_examples/quick_actions/issue/due_quick_action_shared_examples.rb +++ b/spec/support/shared_examples/quick_actions/issue/due_quick_action_shared_examples.rb @@ -1,25 +1,35 @@ # frozen_string_literal: true -shared_examples 'due quick action not available' do - it 'does not set the due date' do - add_note('/due 2016-08-28') +shared_examples 'due quick action' do + context 'due quick action available and date can be added' do + it 'sets the due date accordingly' do + add_note('/due 2016-08-28') - expect(page).not_to have_content 'Commands applied' - expect(page).not_to have_content '/due 2016-08-28' - end -end + expect(page).not_to have_content '/due 2016-08-28' + expect(page).to have_content 'Commands applied' + + visit project_issue_path(project, issue) -shared_examples 'due quick action available and date can be added' do - it 'sets the due date accordingly' do - add_note('/due 2016-08-28') + page.within '.due_date' do + expect(page).to have_content 'Aug 28, 2016' + end + end + end - expect(page).not_to have_content '/due 2016-08-28' - expect(page).to have_content 'Commands applied' + context 'due quick action not available' do + let(:guest) { create(:user) } + before do + project.add_guest(guest) + gitlab_sign_out + sign_in(guest) + visit project_issue_path(project, issue) + end - visit project_issue_path(project, issue) + it 'does not set the due date' do + add_note('/due 2016-08-28') - page.within '.due_date' do - expect(page).to have_content 'Aug 28, 2016' + expect(page).not_to have_content 'Commands applied' + expect(page).not_to have_content '/due 2016-08-28' end end end -- cgit v1.2.1 From 575ec3af131e9c101edfc50ee563381b37c8076e Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Mon, 8 Apr 2019 10:50:39 +0100 Subject: Add issue links to Danger roulette comments --- danger/roulette/Dangerfile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/danger/roulette/Dangerfile b/danger/roulette/Dangerfile index 81ee0397bdc..406dc2c9724 100644 --- a/danger/roulette/Dangerfile +++ b/danger/roulette/Dangerfile @@ -35,7 +35,10 @@ def spin(team, project, category) maintainers = team.select { |member| member.maintainer?(project, category) } # TODO: filter out people who are currently not in the office + # https://gitlab.com/gitlab-org/gitlab-ce/issues/57652 + # # TODO: take CODEOWNERS into account? + # https://gitlab.com/gitlab-org/gitlab-ce/issues/57653 # Make traintainers have triple the chance to be picked as a reviewer reviewer = (reviewers + traintainers + traintainers).sample -- cgit v1.2.1 From 28531ab43666b5fdf37e0a70db3bcbf7d3f92183 Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Mon, 8 Apr 2019 11:44:57 +0100 Subject: Pick reviewers based on branch name Change reviewer roulette to always pick the same reviewers for the same branch name. We do this by: 1. Making the branch name 'canonical' across CE and EE by stripping a leading 'ce-' or 'ee-' and a trailing '-ce' or '-ee'. If people are following our branch naming guidelines, this should give the same branch name in both repos. 2. Converting the branch name to a stable integer by taking the integer form of its MD5. 3. Passing that integer as a seed to Ruby's `Random` class, which 'may be used to ensure repeatable sequences of pseudo-random numbers between different runs of the program' (from the Ruby documentation). The upshot is that the same branch name (in CE and EE) should always pick the same reviewers, and those should be evenly distributed across the set of possible reviewers due to the use of MD5. --- danger/roulette/Dangerfile | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/danger/roulette/Dangerfile b/danger/roulette/Dangerfile index 406dc2c9724..e6820f49ee2 100644 --- a/danger/roulette/Dangerfile +++ b/danger/roulette/Dangerfile @@ -1,5 +1,7 @@ # frozen_string_literal: true +require 'digest/md5' + MESSAGE = < Date: Mon, 8 Apr 2019 14:53:02 +0200 Subject: Remove EE-specific changes from FilteredSearchBoards (cherry picked from commit 250c9b9ecfc35b6b828f6e1a471a803f74daf7f2) --- app/assets/javascripts/boards/filtered_search_boards.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/assets/javascripts/boards/filtered_search_boards.js b/app/assets/javascripts/boards/filtered_search_boards.js index c14d69c5d18..6b54e8baefb 100644 --- a/app/assets/javascripts/boards/filtered_search_boards.js +++ b/app/assets/javascripts/boards/filtered_search_boards.js @@ -1,6 +1,8 @@ +import IssuableFilteredSearchTokenKeys from 'ee_else_ce/filtered_search/issuable_filtered_search_token_keys'; import FilteredSearchContainer from '../filtered_search/container'; import FilteredSearchManager from '../filtered_search/filtered_search_manager'; import boardsStore from './stores/boards_store'; +import { isEE } from '~/lib/utils/common_utils'; export default class FilteredSearchBoards extends FilteredSearchManager { constructor(store, updateUrl = false, cantEdit = []) { @@ -8,6 +10,8 @@ export default class FilteredSearchBoards extends FilteredSearchManager { page: 'boards', isGroupDecendent: true, stateFiltersSelector: '.issues-state-filters', + isGroup: isEE(), + filteredSearchTokenKeys: IssuableFilteredSearchTokenKeys, }); this.store = store; -- cgit v1.2.1 From 32cc246f63b7c63f82f32776af1d66d50ad42517 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Mon, 8 Apr 2019 15:00:36 +0100 Subject: Fixed EE differences in note_body.vue --- app/assets/javascripts/notes/components/note_body.vue | 9 ++++++--- app/assets/javascripts/notes/mixins/get_discussion.js | 7 +++++++ 2 files changed, 13 insertions(+), 3 deletions(-) create mode 100644 app/assets/javascripts/notes/mixins/get_discussion.js diff --git a/app/assets/javascripts/notes/components/note_body.vue b/app/assets/javascripts/notes/components/note_body.vue index ff303d0f55a..fbf75ed0e41 100644 --- a/app/assets/javascripts/notes/components/note_body.vue +++ b/app/assets/javascripts/notes/components/note_body.vue @@ -1,6 +1,7 @@