diff options
Diffstat (limited to 'spec/services/projects')
82 files changed, 859 insertions, 592 deletions
diff --git a/spec/services/projects/after_rename_service_spec.rb b/spec/services/projects/after_rename_service_spec.rb index 72bb0adbf56..3097d6d1498 100644 --- a/spec/services/projects/after_rename_service_spec.rb +++ b/spec/services/projects/after_rename_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::AfterRenameService do +RSpec.describe Projects::AfterRenameService, feature_category: :projects do let(:legacy_storage) { Storage::LegacyProject.new(project) } let(:hashed_storage) { Storage::Hashed.new(project) } let!(:path_before_rename) { project.path } diff --git a/spec/services/projects/alerting/notify_service_spec.rb b/spec/services/projects/alerting/notify_service_spec.rb index aa2ef39bf98..8cd9b5d3e00 100644 --- a/spec/services/projects/alerting/notify_service_spec.rb +++ b/spec/services/projects/alerting/notify_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::Alerting::NotifyService do +RSpec.describe Projects::Alerting::NotifyService, feature_category: :projects do let_it_be_with_reload(:project) { create(:project) } let(:payload) { ActionController::Parameters.new(payload_raw).permit! } diff --git a/spec/services/projects/all_issues_count_service_spec.rb b/spec/services/projects/all_issues_count_service_spec.rb index d7e35991940..e8e08a25c45 100644 --- a/spec/services/projects/all_issues_count_service_spec.rb +++ b/spec/services/projects/all_issues_count_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::AllIssuesCountService, :use_clean_rails_memory_store_caching do +RSpec.describe Projects::AllIssuesCountService, :use_clean_rails_memory_store_caching, feature_category: :projects do let_it_be(:group) { create(:group, :public) } let_it_be(:project) { create(:project, :public, namespace: group) } let_it_be(:banned_user) { create(:user, :banned) } diff --git a/spec/services/projects/all_merge_requests_count_service_spec.rb b/spec/services/projects/all_merge_requests_count_service_spec.rb index 13954d688aa..ca10fbc00ad 100644 --- a/spec/services/projects/all_merge_requests_count_service_spec.rb +++ b/spec/services/projects/all_merge_requests_count_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::AllMergeRequestsCountService, :use_clean_rails_memory_store_caching do +RSpec.describe Projects::AllMergeRequestsCountService, :use_clean_rails_memory_store_caching, feature_category: :projects do let_it_be(:project) { create(:project) } subject { described_class.new(project) } @@ -11,18 +11,9 @@ RSpec.describe Projects::AllMergeRequestsCountService, :use_clean_rails_memory_s describe '#count' do it 'returns the number of all merge requests' do - create(:merge_request, - :opened, - source_project: project, - target_project: project) - create(:merge_request, - :closed, - source_project: project, - target_project: project) - create(:merge_request, - :merged, - source_project: project, - target_project: project) + create(:merge_request, :opened, source_project: project, target_project: project) + create(:merge_request, :closed, source_project: project, target_project: project) + create(:merge_request, :merged, source_project: project, target_project: project) expect(subject.count).to eq(3) end diff --git a/spec/services/projects/android_target_platform_detector_service_spec.rb b/spec/services/projects/android_target_platform_detector_service_spec.rb deleted file mode 100644 index 74fd320bb48..00000000000 --- a/spec/services/projects/android_target_platform_detector_service_spec.rb +++ /dev/null @@ -1,30 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe Projects::AndroidTargetPlatformDetectorService do - let_it_be(:project) { build(:project) } - - subject { described_class.new(project).execute } - - before do - allow(Gitlab::FileFinder).to receive(:new) { finder } - end - - context 'when project is not an Android project' do - let(:finder) { instance_double(Gitlab::FileFinder, find: []) } - - it { is_expected.to be_nil } - end - - context 'when project is an Android project' do - let(:finder) { instance_double(Gitlab::FileFinder) } - - before do - query = described_class::MANIFEST_FILE_SEARCH_QUERY - allow(finder).to receive(:find).with(query) { [instance_double(Gitlab::Search::FoundBlob)] } - end - - it { is_expected.to eq :android } - end -end diff --git a/spec/services/projects/apple_target_platform_detector_service_spec.rb b/spec/services/projects/apple_target_platform_detector_service_spec.rb index 6391161824c..787faaa0f79 100644 --- a/spec/services/projects/apple_target_platform_detector_service_spec.rb +++ b/spec/services/projects/apple_target_platform_detector_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::AppleTargetPlatformDetectorService do +RSpec.describe Projects::AppleTargetPlatformDetectorService, feature_category: :projects do let_it_be(:project) { build(:project) } subject { described_class.new(project).execute } diff --git a/spec/services/projects/auto_devops/disable_service_spec.rb b/spec/services/projects/auto_devops/disable_service_spec.rb index 1f161990fb2..fd70362a53f 100644 --- a/spec/services/projects/auto_devops/disable_service_spec.rb +++ b/spec/services/projects/auto_devops/disable_service_spec.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true require 'spec_helper' -RSpec.describe Projects::AutoDevops::DisableService, '#execute' do +RSpec.describe Projects::AutoDevops::DisableService, '#execute', feature_category: :auto_devops do let(:project) { create(:project, :repository, :auto_devops) } let(:auto_devops) { project.auto_devops } diff --git a/spec/services/projects/autocomplete_service_spec.rb b/spec/services/projects/autocomplete_service_spec.rb index bc95a1f3c8b..9d3075874a2 100644 --- a/spec/services/projects/autocomplete_service_spec.rb +++ b/spec/services/projects/autocomplete_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::AutocompleteService do +RSpec.describe Projects::AutocompleteService, feature_category: :projects do describe '#issues' do describe 'confidential issues' do let(:author) { create(:user) } diff --git a/spec/services/projects/batch_open_issues_count_service_spec.rb b/spec/services/projects/batch_open_issues_count_service_spec.rb index 89a4abbf9c9..d29115a697f 100644 --- a/spec/services/projects/batch_open_issues_count_service_spec.rb +++ b/spec/services/projects/batch_open_issues_count_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::BatchOpenIssuesCountService do +RSpec.describe Projects::BatchOpenIssuesCountService, feature_category: :projects do let!(:project_1) { create(:project) } let!(:project_2) { create(:project) } diff --git a/spec/services/projects/batch_open_merge_requests_count_service_spec.rb b/spec/services/projects/batch_open_merge_requests_count_service_spec.rb new file mode 100644 index 00000000000..96fc6c5e9dd --- /dev/null +++ b/spec/services/projects/batch_open_merge_requests_count_service_spec.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Projects::BatchOpenMergeRequestsCountService, feature_category: :code_review_workflow do + subject { described_class.new([project_1, project_2]) } + + let_it_be(:project_1) { create(:project) } + let_it_be(:project_2) { create(:project) } + + describe '#refresh_cache_and_retrieve_data', :use_clean_rails_memory_store_caching do + before do + create(:merge_request, source_project: project_1, target_project: project_1) + create(:merge_request, source_project: project_2, target_project: project_2) + end + + it 'refreshes cache keys correctly when cache is clean', :aggregate_failures do + subject.refresh_cache_and_retrieve_data + + expect(Rails.cache.read(get_cache_key(subject, project_1))).to eq(1) + expect(Rails.cache.read(get_cache_key(subject, project_2))).to eq(1) + + expect { subject.refresh_cache_and_retrieve_data }.not_to exceed_query_limit(0) + end + end + + def get_cache_key(subject, project) + subject.count_service + .new(project) + .cache_key + end +end diff --git a/spec/services/projects/blame_service_spec.rb b/spec/services/projects/blame_service_spec.rb deleted file mode 100644 index 52b0ed3412d..00000000000 --- a/spec/services/projects/blame_service_spec.rb +++ /dev/null @@ -1,131 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe Projects::BlameService, :aggregate_failures do - subject(:service) { described_class.new(blob, commit, params) } - - let_it_be(:project) { create(:project, :repository) } - let_it_be(:commit) { project.repository.commit } - let_it_be(:blob) { project.repository.blob_at('HEAD', 'README.md') } - - let(:params) { { page: page } } - let(:page) { nil } - - before do - stub_const("#{described_class.name}::PER_PAGE", 2) - end - - describe '#blame' do - subject { service.blame } - - it 'returns a correct Gitlab::Blame object' do - is_expected.to be_kind_of(Gitlab::Blame) - - expect(subject.blob).to eq(blob) - expect(subject.commit).to eq(commit) - expect(subject.range).to eq(1..2) - end - - describe 'Pagination range calculation' do - subject { service.blame.range } - - context 'with page = 1' do - let(:page) { 1 } - - it { is_expected.to eq(1..2) } - end - - context 'with page = 2' do - let(:page) { 2 } - - it { is_expected.to eq(3..4) } - end - - context 'with page = 3 (overlimit)' do - let(:page) { 3 } - - it { is_expected.to eq(1..2) } - end - - context 'with page = 0 (incorrect)' do - let(:page) { 0 } - - it { is_expected.to eq(1..2) } - end - - context 'when user disabled the pagination' do - let(:params) { super().merge(no_pagination: 1) } - - it { is_expected.to be_nil } - end - - context 'when feature flag disabled' do - before do - stub_feature_flags(blame_page_pagination: false) - end - - it { is_expected.to be_nil } - end - end - end - - describe '#pagination' do - subject { service.pagination } - - it 'returns a pagination object' do - is_expected.to be_kind_of(Kaminari::PaginatableArray) - - expect(subject.current_page).to eq(1) - expect(subject.total_pages).to eq(2) - expect(subject.total_count).to eq(4) - end - - context 'when user disabled the pagination' do - let(:params) { super().merge(no_pagination: 1) } - - it { is_expected.to be_nil } - end - - context 'when feature flag disabled' do - before do - stub_feature_flags(blame_page_pagination: false) - end - - it { is_expected.to be_nil } - end - - context 'when per_page is above the global max per page limit' do - before do - stub_const("#{described_class.name}::PER_PAGE", 1000) - allow(blob).to receive_message_chain(:data, :lines, :count) { 500 } - end - - it 'returns a correct pagination object' do - is_expected.to be_kind_of(Kaminari::PaginatableArray) - - expect(subject.current_page).to eq(1) - expect(subject.total_pages).to eq(1) - expect(subject.total_count).to eq(500) - end - end - - describe 'Pagination attributes' do - using RSpec::Parameterized::TableSyntax - - where(:page, :current_page, :total_pages) do - 1 | 1 | 2 - 2 | 2 | 2 - 3 | 1 | 2 # Overlimit - 0 | 1 | 2 # Incorrect - end - - with_them do - it 'returns the correct pagination attributes' do - expect(subject.current_page).to eq(current_page) - expect(subject.total_pages).to eq(total_pages) - end - end - end - end -end diff --git a/spec/services/projects/branches_by_mode_service_spec.rb b/spec/services/projects/branches_by_mode_service_spec.rb index 9a63563b37b..bfe76b34310 100644 --- a/spec/services/projects/branches_by_mode_service_spec.rb +++ b/spec/services/projects/branches_by_mode_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::BranchesByModeService do +RSpec.describe Projects::BranchesByModeService, feature_category: :source_code_management do let_it_be(:user) { create(:user) } let_it_be(:project) { create(:project, :repository) } diff --git a/spec/services/projects/cleanup_service_spec.rb b/spec/services/projects/cleanup_service_spec.rb index f2c052d9397..533a09f7bc7 100644 --- a/spec/services/projects/cleanup_service_spec.rb +++ b/spec/services/projects/cleanup_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::CleanupService do +RSpec.describe Projects::CleanupService, feature_category: :source_code_management do subject(:service) { described_class.new(project) } describe '.enqueue' do diff --git a/spec/services/projects/container_repository/cleanup_tags_service_spec.rb b/spec/services/projects/container_repository/cleanup_tags_service_spec.rb index 8311c4e4d9b..b8ad63d9b8a 100644 --- a/spec/services/projects/container_repository/cleanup_tags_service_spec.rb +++ b/spec/services/projects/container_repository/cleanup_tags_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::ContainerRepository::CleanupTagsService do +RSpec.describe Projects::ContainerRepository::CleanupTagsService, feature_category: :container_registry do let_it_be_with_reload(:container_repository) { create(:container_repository) } let_it_be(:user) { container_repository.project.owner } @@ -77,7 +77,7 @@ RSpec.describe Projects::ContainerRepository::CleanupTagsService do context 'with a migrated repository' do before do - container_repository.update_column(:migration_state, :import_done) + allow(container_repository).to receive(:migrated?).and_return(true) end context 'supporting the gitlab api' do @@ -99,8 +99,7 @@ RSpec.describe Projects::ContainerRepository::CleanupTagsService do context 'with a non migrated repository' do before do - container_repository.update_column(:migration_state, :default) - container_repository.update!(created_at: ContainerRepository::MIGRATION_PHASE_1_ENDED_AT - 1.week) + allow(container_repository).to receive(:migrated?).and_return(false) end it_behaves_like 'calling service', ::Projects::ContainerRepository::ThirdParty::CleanupTagsService, extra_log_data: { third_party_cleanup_tags_service: true } diff --git a/spec/services/projects/container_repository/delete_tags_service_spec.rb b/spec/services/projects/container_repository/delete_tags_service_spec.rb index 9e6849aa514..5b67d614dfb 100644 --- a/spec/services/projects/container_repository/delete_tags_service_spec.rb +++ b/spec/services/projects/container_repository/delete_tags_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::ContainerRepository::DeleteTagsService do +RSpec.describe Projects::ContainerRepository::DeleteTagsService, feature_category: :container_registry do using RSpec::Parameterized::TableSyntax include_context 'container repository delete tags service shared context' diff --git a/spec/services/projects/container_repository/destroy_service_spec.rb b/spec/services/projects/container_repository/destroy_service_spec.rb index fed1d13daa5..a142360f99d 100644 --- a/spec/services/projects/container_repository/destroy_service_spec.rb +++ b/spec/services/projects/container_repository/destroy_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::ContainerRepository::DestroyService do +RSpec.describe Projects::ContainerRepository::DestroyService, feature_category: :container_registry do let_it_be(:user) { create(:user) } let_it_be(:project) { create(:project, :private) } let_it_be(:params) { {} } diff --git a/spec/services/projects/container_repository/gitlab/cleanup_tags_service_spec.rb b/spec/services/projects/container_repository/gitlab/cleanup_tags_service_spec.rb index b06a5709bd5..f662d8bfc0c 100644 --- a/spec/services/projects/container_repository/gitlab/cleanup_tags_service_spec.rb +++ b/spec/services/projects/container_repository/gitlab/cleanup_tags_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::ContainerRepository::Gitlab::CleanupTagsService do +RSpec.describe Projects::ContainerRepository::Gitlab::CleanupTagsService, feature_category: :container_registry do using RSpec::Parameterized::TableSyntax include_context 'for a cleanup tags service' @@ -11,11 +11,13 @@ RSpec.describe Projects::ContainerRepository::Gitlab::CleanupTagsService do let_it_be(:user) { create(:user) } let_it_be(:project, reload: true) { create(:project, :private) } - let(:repository) { create(:container_repository, :root, :import_done, project: project) } + let(:repository) { create(:container_repository, :root, project: project) } let(:service) { described_class.new(container_repository: repository, current_user: user, params: params) } let(:tags) { %w[latest A Ba Bb C D E] } before do + allow(repository).to receive(:migrated?).and_return(true) + project.add_maintainer(user) if user stub_container_registry_config(enabled: true) @@ -47,23 +49,23 @@ RSpec.describe Projects::ContainerRepository::Gitlab::CleanupTagsService do let(:tags_page_size) { 2 } it_behaves_like 'when regex matching everything is specified', - delete_expectations: [%w[A], %w[Ba Bb], %w[C D], %w[E]] + delete_expectations: [%w[A], %w[Ba Bb], %w[C D], %w[E]] it_behaves_like 'when regex matching everything is specified and latest is not kept', - delete_expectations: [%w[latest A], %w[Ba Bb], %w[C D], %w[E]] + delete_expectations: [%w[latest A], %w[Ba Bb], %w[C D], %w[E]] it_behaves_like 'when delete regex matching specific tags is used' it_behaves_like 'when delete regex matching specific tags is used with overriding allow regex' it_behaves_like 'with allow regex value', - delete_expectations: [%w[A], %w[C D], %w[E]] + delete_expectations: [%w[A], %w[C D], %w[E]] it_behaves_like 'when keeping only N tags', - delete_expectations: [%w[Bb]] + delete_expectations: [%w[Bb]] it_behaves_like 'when not keeping N tags', - delete_expectations: [%w[A], %w[Ba Bb], %w[C]] + delete_expectations: [%w[A], %w[Ba Bb], %w[C]] context 'when removing keeping only 3' do let(:params) do @@ -77,13 +79,13 @@ RSpec.describe Projects::ContainerRepository::Gitlab::CleanupTagsService do end it_behaves_like 'when removing older than 1 day', - delete_expectations: [%w[Ba Bb], %w[C]] + delete_expectations: [%w[Ba Bb], %w[C]] it_behaves_like 'when combining all parameters', - delete_expectations: [%w[Bb], %w[C]] + delete_expectations: [%w[Bb], %w[C]] it_behaves_like 'when running a container_expiration_policy', - delete_expectations: [%w[Bb], %w[C]] + delete_expectations: [%w[Bb], %w[C]] context 'with a timeout' do let(:params) do @@ -111,7 +113,7 @@ RSpec.describe Projects::ContainerRepository::Gitlab::CleanupTagsService do end it_behaves_like 'when regex matching everything is specified', - delete_expectations: [%w[A], %w[Ba Bb], %w[C D], %w[E]] + delete_expectations: [%w[A], %w[Ba Bb], %w[C D], %w[E]] end end end @@ -120,32 +122,46 @@ RSpec.describe Projects::ContainerRepository::Gitlab::CleanupTagsService do let(:tags_page_size) { 1000 } it_behaves_like 'when regex matching everything is specified', - delete_expectations: [%w[A Ba Bb C D E]] + delete_expectations: [%w[A Ba Bb C D E]] it_behaves_like 'when delete regex matching specific tags is used' it_behaves_like 'when delete regex matching specific tags is used with overriding allow regex' it_behaves_like 'with allow regex value', - delete_expectations: [%w[A C D E]] + delete_expectations: [%w[A C D E]] it_behaves_like 'when keeping only N tags', - delete_expectations: [%w[Ba Bb C]] + delete_expectations: [%w[Ba Bb C]] it_behaves_like 'when not keeping N tags', - delete_expectations: [%w[A Ba Bb C]] + delete_expectations: [%w[A Ba Bb C]] it_behaves_like 'when removing keeping only 3', - delete_expectations: [%w[Ba Bb C]] + delete_expectations: [%w[Ba Bb C]] it_behaves_like 'when removing older than 1 day', - delete_expectations: [%w[Ba Bb C]] + delete_expectations: [%w[Ba Bb C]] it_behaves_like 'when combining all parameters', - delete_expectations: [%w[Ba Bb C]] + delete_expectations: [%w[Ba Bb C]] it_behaves_like 'when running a container_expiration_policy', - delete_expectations: [%w[Ba Bb C]] + delete_expectations: [%w[Ba Bb C]] + end + + context 'with no tags page' do + let(:tags_page_size) { 1000 } + let(:deleted) { [] } + let(:params) { {} } + + before do + allow(repository.gitlab_api_client) + .to receive(:tags) + .and_return({}) + end + + it { is_expected.to eq(expected_service_response(status: :success, deleted: [], original_size: 0)) } end end diff --git a/spec/services/projects/container_repository/gitlab/delete_tags_service_spec.rb b/spec/services/projects/container_repository/gitlab/delete_tags_service_spec.rb index f03912dba80..c4e6c7f4a11 100644 --- a/spec/services/projects/container_repository/gitlab/delete_tags_service_spec.rb +++ b/spec/services/projects/container_repository/gitlab/delete_tags_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::ContainerRepository::Gitlab::DeleteTagsService do +RSpec.describe Projects::ContainerRepository::Gitlab::DeleteTagsService, feature_category: :container_registry do include_context 'container repository delete tags service shared context' let(:service) { described_class.new(repository, tags) } diff --git a/spec/services/projects/container_repository/third_party/cleanup_tags_service_spec.rb b/spec/services/projects/container_repository/third_party/cleanup_tags_service_spec.rb index 7227834b131..836e722eb99 100644 --- a/spec/services/projects/container_repository/third_party/cleanup_tags_service_spec.rb +++ b/spec/services/projects/container_repository/third_party/cleanup_tags_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::ContainerRepository::ThirdParty::CleanupTagsService, :clean_gitlab_redis_cache do +RSpec.describe Projects::ContainerRepository::ThirdParty::CleanupTagsService, :clean_gitlab_redis_cache, feature_category: :container_registry do using RSpec::Parameterized::TableSyntax include_context 'for a cleanup tags service' @@ -42,112 +42,112 @@ RSpec.describe Projects::ContainerRepository::ThirdParty::CleanupTagsService, :c subject { service.execute } it_behaves_like 'when regex matching everything is specified', - delete_expectations: [%w[A Ba Bb C D E]], - service_response_extra: { - before_truncate_size: 6, - after_truncate_size: 6, - before_delete_size: 6, - cached_tags_count: 0 - }, - supports_caching: true + delete_expectations: [%w[A Ba Bb C D E]], + service_response_extra: { + before_truncate_size: 6, + after_truncate_size: 6, + before_delete_size: 6, + cached_tags_count: 0 + }, + supports_caching: true it_behaves_like 'when regex matching everything is specified and latest is not kept', - delete_expectations: [%w[A Ba Bb C D E latest]], - service_response_extra: { - before_truncate_size: 7, - after_truncate_size: 7, - before_delete_size: 7, - cached_tags_count: 0 - }, - supports_caching: true + delete_expectations: [%w[A Ba Bb C D E latest]], + service_response_extra: { + before_truncate_size: 7, + after_truncate_size: 7, + before_delete_size: 7, + cached_tags_count: 0 + }, + supports_caching: true it_behaves_like 'when delete regex matching specific tags is used', - service_response_extra: { - before_truncate_size: 2, - after_truncate_size: 2, - before_delete_size: 2, - cached_tags_count: 0 - }, - supports_caching: true + service_response_extra: { + before_truncate_size: 2, + after_truncate_size: 2, + before_delete_size: 2, + cached_tags_count: 0 + }, + supports_caching: true it_behaves_like 'when delete regex matching specific tags is used with overriding allow regex', - service_response_extra: { - before_truncate_size: 1, - after_truncate_size: 1, - before_delete_size: 1, - cached_tags_count: 0 - }, - supports_caching: true + service_response_extra: { + before_truncate_size: 1, + after_truncate_size: 1, + before_delete_size: 1, + cached_tags_count: 0 + }, + supports_caching: true it_behaves_like 'with allow regex value', - delete_expectations: [%w[A C D E]], - service_response_extra: { - before_truncate_size: 4, - after_truncate_size: 4, - before_delete_size: 4, - cached_tags_count: 0 - }, - supports_caching: true + delete_expectations: [%w[A C D E]], + service_response_extra: { + before_truncate_size: 4, + after_truncate_size: 4, + before_delete_size: 4, + cached_tags_count: 0 + }, + supports_caching: true it_behaves_like 'when keeping only N tags', - delete_expectations: [%w[Bb Ba C]], - service_response_extra: { - before_truncate_size: 4, - after_truncate_size: 4, - before_delete_size: 3, - cached_tags_count: 0 - }, - supports_caching: true + delete_expectations: [%w[Bb Ba C]], + service_response_extra: { + before_truncate_size: 4, + after_truncate_size: 4, + before_delete_size: 3, + cached_tags_count: 0 + }, + supports_caching: true it_behaves_like 'when not keeping N tags', - delete_expectations: [%w[A Ba Bb C]], - service_response_extra: { - before_truncate_size: 4, - after_truncate_size: 4, - before_delete_size: 4, - cached_tags_count: 0 - }, - supports_caching: true + delete_expectations: [%w[A Ba Bb C]], + service_response_extra: { + before_truncate_size: 4, + after_truncate_size: 4, + before_delete_size: 4, + cached_tags_count: 0 + }, + supports_caching: true it_behaves_like 'when removing keeping only 3', - delete_expectations: [%w[Bb Ba C]], - service_response_extra: { - before_truncate_size: 6, - after_truncate_size: 6, - before_delete_size: 3, - cached_tags_count: 0 - }, - supports_caching: true + delete_expectations: [%w[Bb Ba C]], + service_response_extra: { + before_truncate_size: 6, + after_truncate_size: 6, + before_delete_size: 3, + cached_tags_count: 0 + }, + supports_caching: true it_behaves_like 'when removing older than 1 day', - delete_expectations: [%w[Ba Bb C]], - service_response_extra: { - before_truncate_size: 6, - after_truncate_size: 6, - before_delete_size: 3, - cached_tags_count: 0 - }, - supports_caching: true + delete_expectations: [%w[Ba Bb C]], + service_response_extra: { + before_truncate_size: 6, + after_truncate_size: 6, + before_delete_size: 3, + cached_tags_count: 0 + }, + supports_caching: true it_behaves_like 'when combining all parameters', - delete_expectations: [%w[Bb Ba C]], - service_response_extra: { - before_truncate_size: 6, - after_truncate_size: 6, - before_delete_size: 3, - cached_tags_count: 0 - }, - supports_caching: true + delete_expectations: [%w[Bb Ba C]], + service_response_extra: { + before_truncate_size: 6, + after_truncate_size: 6, + before_delete_size: 3, + cached_tags_count: 0 + }, + supports_caching: true it_behaves_like 'when running a container_expiration_policy', - delete_expectations: [%w[Bb Ba C]], - service_response_extra: { - before_truncate_size: 6, - after_truncate_size: 6, - before_delete_size: 3, - cached_tags_count: 0 - }, - supports_caching: true + delete_expectations: [%w[Bb Ba C]], + service_response_extra: { + before_truncate_size: 6, + after_truncate_size: 6, + before_delete_size: 3, + cached_tags_count: 0 + }, + supports_caching: true context 'when running a container_expiration_policy with caching' do let(:user) { nil } diff --git a/spec/services/projects/container_repository/third_party/delete_tags_service_spec.rb b/spec/services/projects/container_repository/third_party/delete_tags_service_spec.rb index 4de36452684..0c297b6e1f7 100644 --- a/spec/services/projects/container_repository/third_party/delete_tags_service_spec.rb +++ b/spec/services/projects/container_repository/third_party/delete_tags_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::ContainerRepository::ThirdParty::DeleteTagsService do +RSpec.describe Projects::ContainerRepository::ThirdParty::DeleteTagsService, feature_category: :container_registry do include_context 'container repository delete tags service shared context' let(:service) { described_class.new(repository, tags) } diff --git a/spec/services/projects/count_service_spec.rb b/spec/services/projects/count_service_spec.rb index 11b2b57a277..71940fa396e 100644 --- a/spec/services/projects/count_service_spec.rb +++ b/spec/services/projects/count_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::CountService do +RSpec.describe Projects::CountService, feature_category: :projects do let(:project) { build(:project, id: 1) } let(:service) { described_class.new(project) } diff --git a/spec/services/projects/create_from_template_service_spec.rb b/spec/services/projects/create_from_template_service_spec.rb index fba6225b87a..a3fdb258f75 100644 --- a/spec/services/projects/create_from_template_service_spec.rb +++ b/spec/services/projects/create_from_template_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::CreateFromTemplateService do +RSpec.describe Projects::CreateFromTemplateService, feature_category: :projects do let(:user) { create(:user) } let(:template_name) { 'rails' } let(:project_params) do diff --git a/spec/services/projects/create_service_spec.rb b/spec/services/projects/create_service_spec.rb index e435db4efa6..303a98cb35b 100644 --- a/spec/services/projects/create_service_spec.rb +++ b/spec/services/projects/create_service_spec.rb @@ -254,6 +254,27 @@ RSpec.describe Projects::CreateService, '#execute', feature_category: :projects end it_behaves_like 'has sync-ed traversal_ids' + + context 'when project is an import' do + before do + stub_application_setting(import_sources: ['gitlab_project']) + end + + context 'when user is not allowed to import projects' do + let(:group) do + create(:group).tap do |group| + group.add_developer(user) + end + end + + it 'does not create the project' do + project = create_project(user, opts.merge!(namespace_id: group.id, import_type: 'gitlab_project')) + + expect(project).not_to be_persisted + expect(project.errors.messages[:user].first).to eq('is not allowed to import projects') + end + end + end end context 'group sharing', :sidekiq_inline do @@ -339,9 +360,12 @@ RSpec.describe Projects::CreateService, '#execute', feature_category: :projects before do group.add_maintainer(group_maintainer) - create(:group_group_link, shared_group: subgroup_for_projects, - shared_with_group: subgroup_for_access, - group_access: share_max_access_level) + create( + :group_group_link, + shared_group: subgroup_for_projects, + shared_with_group: subgroup_for_access, + group_access: share_max_access_level + ) end context 'membership is higher from group hierarchy' do @@ -716,16 +740,34 @@ RSpec.describe Projects::CreateService, '#execute', feature_category: :projects end end - context 'and a default_branch_name is specified' do + context 'and default_branch is specified' do before do - allow(Gitlab::CurrentSettings).to receive(:default_branch_name).and_return('example_branch') + opts[:default_branch] = 'example_branch' end it 'creates the correct branch' do - branches = project.repository.branches + expect(project.repository.branch_names).to contain_exactly('example_branch') + end - expect(branches.size).to eq(1) - expect(branches.collect(&:name)).to contain_exactly('example_branch') + it_behaves_like 'a repo with a README.md' do + let(:expected_content) do + <<~MARKDOWN + cd existing_repo + git remote add origin #{project.http_url_to_repo} + git branch -M example_branch + git push -uf origin example_branch + MARKDOWN + end + end + end + + context 'and the default branch setting is configured' do + before do + allow(Gitlab::CurrentSettings).to receive(:default_branch_name).and_return('example_branch') + end + + it 'creates the correct branch' do + expect(project.repository.branch_names).to contain_exactly('example_branch') end it_behaves_like 'a repo with a README.md' do @@ -956,11 +998,11 @@ RSpec.describe Projects::CreateService, '#execute', feature_category: :projects receive(:perform_async).and_call_original ) expect(AuthorizedProjectUpdate::UserRefreshFromReplicaWorker).to( - receive(:bulk_perform_in) - .with(1.hour, - array_including([user.id], [other_user.id]), - batch_delay: 30.seconds, batch_size: 100) - .and_call_original + receive(:bulk_perform_in).with( + 1.hour, + array_including([user.id], [other_user.id]), + batch_delay: 30.seconds, batch_size: 100 + ).and_call_original ) project = create_project(user, opts) diff --git a/spec/services/projects/deploy_tokens/create_service_spec.rb b/spec/services/projects/deploy_tokens/create_service_spec.rb index 831dbc06588..96458a51fb4 100644 --- a/spec/services/projects/deploy_tokens/create_service_spec.rb +++ b/spec/services/projects/deploy_tokens/create_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::DeployTokens::CreateService do +RSpec.describe Projects::DeployTokens::CreateService, feature_category: :continuous_delivery do it_behaves_like 'a deploy token creation service' do let(:entity) { create(:project) } let(:deploy_token_class) { ProjectDeployToken } diff --git a/spec/services/projects/deploy_tokens/destroy_service_spec.rb b/spec/services/projects/deploy_tokens/destroy_service_spec.rb index edb2345aa6c..3d0323c60ba 100644 --- a/spec/services/projects/deploy_tokens/destroy_service_spec.rb +++ b/spec/services/projects/deploy_tokens/destroy_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::DeployTokens::DestroyService do +RSpec.describe Projects::DeployTokens::DestroyService, feature_category: :continuous_delivery do it_behaves_like 'a deploy token deletion service' do let_it_be(:entity) { create(:project) } let_it_be(:deploy_token_class) { ProjectDeployToken } diff --git a/spec/services/projects/destroy_service_spec.rb b/spec/services/projects/destroy_service_spec.rb index 0689a65c2f4..665f930a0a8 100644 --- a/spec/services/projects/destroy_service_spec.rb +++ b/spec/services/projects/destroy_service_spec.rb @@ -207,9 +207,11 @@ RSpec.describe Projects::DestroyService, :aggregate_failures, :event_store_publi context 'when project has exports' do let!(:project_with_export) do create(:project, :repository, namespace: user.namespace).tap do |project| - create(:import_export_upload, - project: project, - export_file: fixture_file_upload('spec/fixtures/project_export.tar.gz')) + create( + :import_export_upload, + project: project, + export_file: fixture_file_upload('spec/fixtures/project_export.tar.gz') + ) end end @@ -337,8 +339,7 @@ RSpec.describe Projects::DestroyService, :aggregate_failures, :event_store_publi let(:container_repository) { create(:container_repository) } before do - stub_container_registry_tags(repository: project.full_path + '/image', - tags: ['tag']) + stub_container_registry_tags(repository: project.full_path + '/image', tags: ['tag']) project.container_repositories << container_repository end @@ -387,8 +388,7 @@ RSpec.describe Projects::DestroyService, :aggregate_failures, :event_store_publi context 'when there are tags for legacy root repository' do before do - stub_container_registry_tags(repository: project.full_path, - tags: ['tag']) + stub_container_registry_tags(repository: project.full_path, tags: ['tag']) end context 'when image repository tags deletion succeeds' do @@ -414,8 +414,7 @@ RSpec.describe Projects::DestroyService, :aggregate_failures, :event_store_publi context 'when there are no tags for legacy root repository' do before do - stub_container_registry_tags(repository: project.full_path, - tags: []) + stub_container_registry_tags(repository: project.full_path, tags: []) end it 'does not try to destroy the repository' do diff --git a/spec/services/projects/detect_repository_languages_service_spec.rb b/spec/services/projects/detect_repository_languages_service_spec.rb index cf4c7a5024d..5759f8128d0 100644 --- a/spec/services/projects/detect_repository_languages_service_spec.rb +++ b/spec/services/projects/detect_repository_languages_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::DetectRepositoryLanguagesService, :clean_gitlab_redis_shared_state do +RSpec.describe Projects::DetectRepositoryLanguagesService, :clean_gitlab_redis_shared_state, feature_category: :projects do let_it_be(:project, reload: true) { create(:project, :repository) } subject { described_class.new(project) } diff --git a/spec/services/projects/download_service_spec.rb b/spec/services/projects/download_service_spec.rb index f158b11a9fa..52bdbefe01a 100644 --- a/spec/services/projects/download_service_spec.rb +++ b/spec/services/projects/download_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::DownloadService do +RSpec.describe Projects::DownloadService, feature_category: :projects do describe 'File service' do before do @user = create(:user) diff --git a/spec/services/projects/enable_deploy_key_service_spec.rb b/spec/services/projects/enable_deploy_key_service_spec.rb index c0b3992037e..59c76a96d07 100644 --- a/spec/services/projects/enable_deploy_key_service_spec.rb +++ b/spec/services/projects/enable_deploy_key_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::EnableDeployKeyService do +RSpec.describe Projects::EnableDeployKeyService, feature_category: :continuous_delivery do let(:deploy_key) { create(:deploy_key, public: true) } let(:project) { create(:project) } let(:user) { project.creator } diff --git a/spec/services/projects/fetch_statistics_increment_service_spec.rb b/spec/services/projects/fetch_statistics_increment_service_spec.rb index 16121a42c39..9e24e68fa98 100644 --- a/spec/services/projects/fetch_statistics_increment_service_spec.rb +++ b/spec/services/projects/fetch_statistics_increment_service_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' module Projects - RSpec.describe FetchStatisticsIncrementService do + RSpec.describe FetchStatisticsIncrementService, feature_category: :projects do let(:project) { create(:project) } describe '#execute' do diff --git a/spec/services/projects/fork_service_spec.rb b/spec/services/projects/fork_service_spec.rb index 48756cf774b..4ba72b5870d 100644 --- a/spec/services/projects/fork_service_spec.rb +++ b/spec/services/projects/fork_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::ForkService do +RSpec.describe Projects::ForkService, feature_category: :source_code_management do include ProjectForksHelper shared_examples 'forks count cache refresh' do @@ -22,14 +22,16 @@ RSpec.describe Projects::ForkService do @from_user = create(:user) @from_namespace = @from_user.namespace avatar = fixture_file_upload("spec/fixtures/dk.png", "image/png") - @from_project = create(:project, - :repository, - creator_id: @from_user.id, - namespace: @from_namespace, - star_count: 107, - avatar: avatar, - description: 'wow such project', - external_authorization_classification_label: 'classification-label') + @from_project = create( + :project, + :repository, + creator_id: @from_user.id, + namespace: @from_namespace, + star_count: 107, + avatar: avatar, + description: 'wow such project', + external_authorization_classification_label: 'classification-label' + ) @to_user = create(:user) @to_namespace = @to_user.namespace @from_project.add_member(@to_user, :developer) @@ -148,12 +150,11 @@ RSpec.describe Projects::ForkService do context 'project already exists' do it "fails due to validation, not transaction failure" do - @existing_project = create(:project, :repository, creator_id: @to_user.id, name: @from_project.name, namespace: @to_namespace) + @existing_project = create(:project, :repository, creator_id: @to_user.id, path: @from_project.path, namespace: @to_namespace) @to_project = fork_project(@from_project, @to_user, namespace: @to_namespace, using_service: true) expect(@existing_project).to be_persisted expect(@to_project).not_to be_persisted - expect(@to_project.errors[:name]).to eq(['has already been taken']) expect(@to_project.errors[:path]).to eq(['has already been taken']) end end @@ -258,11 +259,13 @@ RSpec.describe Projects::ForkService do before do @group_owner = create(:user) @developer = create(:user) - @project = create(:project, :repository, - creator_id: @group_owner.id, - star_count: 777, - description: 'Wow, such a cool project!', - ci_config_path: 'debian/salsa-ci.yml') + @project = create( + :project, :repository, + creator_id: @group_owner.id, + star_count: 777, + description: 'Wow, such a cool project!', + ci_config_path: 'debian/salsa-ci.yml' + ) @group = create(:group) @group.add_member(@group_owner, GroupMember::OWNER) @group.add_member(@developer, GroupMember::DEVELOPER) @@ -297,12 +300,9 @@ RSpec.describe Projects::ForkService do context 'project already exists in group' do it 'fails due to validation, not transaction failure' do - existing_project = create(:project, :repository, - name: @project.name, - namespace: @group) + existing_project = create(:project, :repository, path: @project.path, namespace: @group) to_project = fork_project(@project, @group_owner, @opts) expect(existing_project.persisted?).to be_truthy - expect(to_project.errors[:name]).to eq(['has already been taken']) expect(to_project.errors[:path]).to eq(['has already been taken']) end end diff --git a/spec/services/projects/forks/sync_service_spec.rb b/spec/services/projects/forks/sync_service_spec.rb new file mode 100644 index 00000000000..aeb53992ed4 --- /dev/null +++ b/spec/services/projects/forks/sync_service_spec.rb @@ -0,0 +1,185 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Projects::Forks::SyncService, feature_category: :source_code_management do + include ProjectForksHelper + include RepoHelpers + + let_it_be(:user) { create(:user) } + let_it_be(:source_project) { create(:project, :repository, :public) } + let_it_be(:project) { fork_project(source_project, user, { repository: true }) } + + let(:fork_branch) { project.default_branch } + let(:service) { described_class.new(project, user, fork_branch) } + + def details + Projects::Forks::Details.new(project, fork_branch) + end + + def expect_to_cancel_exclusive_lease + expect(Gitlab::ExclusiveLease).to receive(:cancel) + end + + describe '#execute' do + context 'when fork is up-to-date with the upstream' do + it 'does not perform merge' do + expect_to_cancel_exclusive_lease + expect(project.repository).not_to receive(:merge_to_branch) + expect(project.repository).not_to receive(:ff_merge) + + expect(service.execute).to be_success + end + end + + context 'when fork is behind the upstream' do + let_it_be(:base_commit) { source_project.commit.sha } + + before_all do + source_project.repository.commit_files( + user, + branch_name: source_project.repository.root_ref, message: 'Commit to root ref', + actions: [{ action: :create, file_path: 'encoding/CHANGELOG', content: 'One more' }] + ) + + source_project.repository.commit_files( + user, + branch_name: source_project.repository.root_ref, message: 'Another commit to root ref', + actions: [{ action: :create, file_path: 'encoding/NEW-CHANGELOG', content: 'One more time' }] + ) + end + + before do + project.repository.create_branch(fork_branch, base_commit) + end + + context 'when fork is not ahead of the upstream' do + let(:fork_branch) { 'fork-without-new-commits' } + + it 'updates the fork using ff merge' do + expect_to_cancel_exclusive_lease + expect(project.commit(fork_branch).sha).to eq(base_commit) + expect(project.repository).to receive(:ff_merge) + .with(user, source_project.commit.sha, fork_branch, target_sha: base_commit) + .and_call_original + + expect do + expect(service.execute).to be_success + end.to change { details.counts }.from({ ahead: 0, behind: 2 }).to({ ahead: 0, behind: 0 }) + end + end + + context 'when fork is ahead of the upstream' do + context 'and has conflicts with the upstream', :use_clean_rails_redis_caching do + let(:fork_branch) { 'fork-with-conflicts' } + + it 'returns an error' do + project.repository.commit_files( + user, + branch_name: fork_branch, message: 'Committing something', + actions: [{ action: :create, file_path: 'encoding/CHANGELOG', content: 'New file' }] + ) + + expect_to_cancel_exclusive_lease + expect(details).not_to have_conflicts + + expect do + result = service.execute + + expect(result).to be_error + expect(result.message).to eq("9:merging commits: merge: there are conflicting files.") + end.not_to change { details.counts } + + expect(details).to have_conflicts + end + end + + context 'and does not have conflicts with the upstream' do + let(:fork_branch) { 'fork-with-new-commits' } + + it 'updates the fork using merge' do + project.repository.commit_files( + user, + branch_name: fork_branch, message: 'Committing completely new changelog', + actions: [{ action: :create, file_path: 'encoding/COMPLETELY-NEW-CHANGELOG', content: 'New file' }] + ) + + commit_message = "Merge branch #{source_project.path}:#{source_project.default_branch} into #{fork_branch}" + expect(project.repository).to receive(:merge_to_branch).with( + user, + source_sha: source_project.commit.sha, + target_branch: fork_branch, + target_sha: project.commit(fork_branch).sha, + message: commit_message + ).and_call_original + expect_to_cancel_exclusive_lease + + expect do + expect(service.execute).to be_success + end.to change { details.counts }.from({ ahead: 1, behind: 2 }).to({ ahead: 2, behind: 0 }) + + commits = project.repository.commits_between(source_project.commit.sha, project.commit(fork_branch).sha) + expect(commits.map(&:message)).to eq([ + "Committing completely new changelog", + commit_message + ]) + end + end + end + + context 'when a merge cannot happen due to another ongoing merge' do + it 'does not merge' do + expect(service).to receive(:perform_merge).and_return(nil) + + result = service.execute + + expect(result).to be_error + expect(result.message).to eq(described_class::ONGOING_MERGE_ERROR) + end + end + + context 'when upstream branch contains lfs reference' do + let(:source_project) { create(:project, :repository, :public) } + let(:project) { fork_project(source_project, user, { repository: true }) } + let(:fork_branch) { 'fork-fetches-lfs-pointers' } + + before do + source_project.change_head('lfs') + + allow(source_project).to receive(:lfs_enabled?).and_return(true) + allow(project).to receive(:lfs_enabled?).and_return(true) + + create_file_in_repo(source_project, 'lfs', 'lfs', 'one.lfs', 'One') + create_file_in_repo(source_project, 'lfs', 'lfs', 'two.lfs', 'Two') + end + + it 'links fetched lfs objects to the fork project', :aggregate_failures do + expect_to_cancel_exclusive_lease + + expect do + expect(service.execute).to be_success + end.to change { project.reload.lfs_objects.size }.from(0).to(2) + .and change { details.counts }.from({ ahead: 0, behind: 3 }).to({ ahead: 0, behind: 0 }) + + expect(project.lfs_objects).to match_array(source_project.lfs_objects) + end + + context 'and there are too many of them for a single sync' do + let(:fork_branch) { 'fork-too-many-lfs-pointers' } + + it 'updates the fork successfully' do + expect_to_cancel_exclusive_lease + stub_const('Projects::LfsPointers::LfsLinkService::MAX_OIDS', 1) + + expect do + result = service.execute + + expect(result).to be_error + expect(result.message).to eq('Too many LFS object ids to link, please push them manually') + end.not_to change { details.counts } + end + end + end + end + end +end diff --git a/spec/services/projects/forks_count_service_spec.rb b/spec/services/projects/forks_count_service_spec.rb index 31662f78973..403d8656b7c 100644 --- a/spec/services/projects/forks_count_service_spec.rb +++ b/spec/services/projects/forks_count_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::ForksCountService, :use_clean_rails_memory_store_caching do +RSpec.describe Projects::ForksCountService, :use_clean_rails_memory_store_caching, feature_category: :source_code_management do let(:project) { build(:project) } subject { described_class.new(project) } diff --git a/spec/services/projects/git_deduplication_service_spec.rb b/spec/services/projects/git_deduplication_service_spec.rb index e6eff936de7..2b9f0974ae2 100644 --- a/spec/services/projects/git_deduplication_service_spec.rb +++ b/spec/services/projects/git_deduplication_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::GitDeduplicationService do +RSpec.describe Projects::GitDeduplicationService, feature_category: :source_code_management do include ExclusiveLeaseHelpers let(:pool) { create(:pool_repository, :ready) } @@ -139,7 +139,7 @@ RSpec.describe Projects::GitDeduplicationService do end it 'fails when a lease is already out' do - expect(service).to receive(:log_error).with("Cannot obtain an exclusive lease for #{lease_key}. There must be another instance already in execution.") + expect(Gitlab::AppJsonLogger).to receive(:error).with({ message: "Cannot obtain an exclusive lease. There must be another instance already in execution.", lease_key: lease_key, class_name: described_class.name, lease_timeout: lease_timeout }) service.execute end diff --git a/spec/services/projects/gitlab_projects_import_service_spec.rb b/spec/services/projects/gitlab_projects_import_service_spec.rb index d32e720a49f..b1468a40212 100644 --- a/spec/services/projects/gitlab_projects_import_service_spec.rb +++ b/spec/services/projects/gitlab_projects_import_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::GitlabProjectsImportService do +RSpec.describe Projects::GitlabProjectsImportService, feature_category: :importers do let_it_be(:namespace) { create(:namespace) } let(:path) { 'test-path' } diff --git a/spec/services/projects/group_links/create_service_spec.rb b/spec/services/projects/group_links/create_service_spec.rb index eae898b4f68..4f2f480cf1c 100644 --- a/spec/services/projects/group_links/create_service_spec.rb +++ b/spec/services/projects/group_links/create_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::GroupLinks::CreateService, '#execute' do +RSpec.describe Projects::GroupLinks::CreateService, '#execute', feature_category: :subgroups do let_it_be(:user) { create :user } let_it_be(:group) { create :group } let_it_be(:project) { create(:project, namespace: create(:namespace, :with_namespace_settings)) } @@ -69,11 +69,11 @@ RSpec.describe Projects::GroupLinks::CreateService, '#execute' do .and_call_original ) expect(AuthorizedProjectUpdate::UserRefreshFromReplicaWorker).to( - receive(:bulk_perform_in) - .with(1.hour, - array_including([user.id], [other_user.id]), - batch_delay: 30.seconds, batch_size: 100) - .and_call_original + receive(:bulk_perform_in).with( + 1.hour, + array_including([user.id], [other_user.id]), + batch_delay: 30.seconds, batch_size: 100 + ).and_call_original ) subject.execute @@ -82,8 +82,7 @@ RSpec.describe Projects::GroupLinks::CreateService, '#execute' do context 'when sharing outside the hierarchy is disabled' do let_it_be(:shared_group_parent) do - create(:group, - namespace_settings: create(:namespace_settings, prevent_sharing_groups_outside_hierarchy: true)) + create(:group, namespace_settings: create(:namespace_settings, prevent_sharing_groups_outside_hierarchy: true)) end let_it_be(:project, reload: true) { create(:project, group: shared_group_parent) } diff --git a/spec/services/projects/group_links/destroy_service_spec.rb b/spec/services/projects/group_links/destroy_service_spec.rb index 89865d6bc3b..76bdd536a0d 100644 --- a/spec/services/projects/group_links/destroy_service_spec.rb +++ b/spec/services/projects/group_links/destroy_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::GroupLinks::DestroyService, '#execute' do +RSpec.describe Projects::GroupLinks::DestroyService, '#execute', feature_category: :subgroups do let_it_be(:user) { create :user } let_it_be(:project) { create(:project, :private) } let_it_be(:group) { create(:group) } @@ -31,10 +31,11 @@ RSpec.describe Projects::GroupLinks::DestroyService, '#execute' do stub_feature_flags(do_not_run_safety_net_auth_refresh_jobs: false) expect(AuthorizedProjectUpdate::UserRefreshFromReplicaWorker).to( - receive(:bulk_perform_in) - .with(1.hour, - [[user.id]], - batch_delay: 30.seconds, batch_size: 100) + receive(:bulk_perform_in).with( + 1.hour, + [[user.id]], + batch_delay: 30.seconds, batch_size: 100 + ) ) subject.execute(group_link) diff --git a/spec/services/projects/group_links/update_service_spec.rb b/spec/services/projects/group_links/update_service_spec.rb index 1acbb770763..4232412cf54 100644 --- a/spec/services/projects/group_links/update_service_spec.rb +++ b/spec/services/projects/group_links/update_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::GroupLinks::UpdateService, '#execute' do +RSpec.describe Projects::GroupLinks::UpdateService, '#execute', feature_category: :subgroups do let_it_be(:user) { create :user } let_it_be(:group) { create :group } let_it_be(:project) { create :project } @@ -45,10 +45,11 @@ RSpec.describe Projects::GroupLinks::UpdateService, '#execute' do stub_feature_flags(do_not_run_safety_net_auth_refresh_jobs: false) expect(AuthorizedProjectUpdate::UserRefreshFromReplicaWorker).to( - receive(:bulk_perform_in) - .with(1.hour, - [[user.id]], - batch_delay: 30.seconds, batch_size: 100) + receive(:bulk_perform_in).with( + 1.hour, + [[user.id]], + batch_delay: 30.seconds, batch_size: 100 + ) ) subject diff --git a/spec/services/projects/hashed_storage/base_attachment_service_spec.rb b/spec/services/projects/hashed_storage/base_attachment_service_spec.rb index 86e3fb3820c..01036fc2d9c 100644 --- a/spec/services/projects/hashed_storage/base_attachment_service_spec.rb +++ b/spec/services/projects/hashed_storage/base_attachment_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::HashedStorage::BaseAttachmentService do +RSpec.describe Projects::HashedStorage::BaseAttachmentService, feature_category: :projects do let(:project) { create(:project, :repository, storage_version: 0, skip_disk_validation: true) } subject(:service) { described_class.new(project: project, old_disk_path: project.full_path, logger: nil) } diff --git a/spec/services/projects/hashed_storage/migrate_attachments_service_spec.rb b/spec/services/projects/hashed_storage/migrate_attachments_service_spec.rb index c8f24c6ce00..39263506bca 100644 --- a/spec/services/projects/hashed_storage/migrate_attachments_service_spec.rb +++ b/spec/services/projects/hashed_storage/migrate_attachments_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::HashedStorage::MigrateAttachmentsService do +RSpec.describe Projects::HashedStorage::MigrateAttachmentsService, feature_category: :projects do subject(:service) { described_class.new(project: project, old_disk_path: project.full_path, logger: nil) } let(:project) { create(:project, :repository, storage_version: 1, skip_disk_validation: true) } diff --git a/spec/services/projects/hashed_storage/migrate_repository_service_spec.rb b/spec/services/projects/hashed_storage/migrate_repository_service_spec.rb index eb8d94ebfa5..bcc914e72b5 100644 --- a/spec/services/projects/hashed_storage/migrate_repository_service_spec.rb +++ b/spec/services/projects/hashed_storage/migrate_repository_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::HashedStorage::MigrateRepositoryService do +RSpec.describe Projects::HashedStorage::MigrateRepositoryService, feature_category: :projects do let(:gitlab_shell) { Gitlab::Shell.new } let(:project) { create(:project, :legacy_storage, :repository, :wiki_repo, :design_repo) } let(:legacy_storage) { Storage::LegacyProject.new(project) } diff --git a/spec/services/projects/hashed_storage/migration_service_spec.rb b/spec/services/projects/hashed_storage/migration_service_spec.rb index ef96c17dd85..89bc55dbaf6 100644 --- a/spec/services/projects/hashed_storage/migration_service_spec.rb +++ b/spec/services/projects/hashed_storage/migration_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::HashedStorage::MigrationService do +RSpec.describe Projects::HashedStorage::MigrationService, feature_category: :projects do let(:project) { create(:project, :empty_repo, :wiki_repo, :legacy_storage) } let(:logger) { double } let!(:project_attachment) { build(:file_uploader, project: project) } @@ -16,9 +16,11 @@ RSpec.describe Projects::HashedStorage::MigrationService do describe '#execute' do context 'repository migration' do let(:repository_service) do - Projects::HashedStorage::MigrateRepositoryService.new(project: project, - old_disk_path: project.full_path, - logger: logger) + Projects::HashedStorage::MigrateRepositoryService.new( + project: project, + old_disk_path: project.full_path, + logger: logger + ) end it 'delegates migration to Projects::HashedStorage::MigrateRepositoryService' do @@ -53,9 +55,11 @@ RSpec.describe Projects::HashedStorage::MigrationService do let(:project) { create(:project, :empty_repo, :wiki_repo, storage_version: ::Project::HASHED_STORAGE_FEATURES[:repository]) } let(:attachments_service) do - Projects::HashedStorage::MigrateAttachmentsService.new(project: project, - old_disk_path: project.full_path, - logger: logger) + Projects::HashedStorage::MigrateAttachmentsService.new( + project: project, + old_disk_path: project.full_path, + logger: logger + ) end it 'delegates migration to Projects::HashedStorage::MigrateRepositoryService' do diff --git a/spec/services/projects/hashed_storage/rollback_attachments_service_spec.rb b/spec/services/projects/hashed_storage/rollback_attachments_service_spec.rb index d4cb46c82ad..95491d63df2 100644 --- a/spec/services/projects/hashed_storage/rollback_attachments_service_spec.rb +++ b/spec/services/projects/hashed_storage/rollback_attachments_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::HashedStorage::RollbackAttachmentsService do +RSpec.describe Projects::HashedStorage::RollbackAttachmentsService, feature_category: :projects do subject(:service) { described_class.new(project: project, old_disk_path: project.disk_path, logger: nil) } let(:project) { create(:project, :repository, skip_disk_validation: true) } diff --git a/spec/services/projects/hashed_storage/rollback_repository_service_spec.rb b/spec/services/projects/hashed_storage/rollback_repository_service_spec.rb index 385c03e6308..19f1856e39a 100644 --- a/spec/services/projects/hashed_storage/rollback_repository_service_spec.rb +++ b/spec/services/projects/hashed_storage/rollback_repository_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::HashedStorage::RollbackRepositoryService, :clean_gitlab_redis_shared_state do +RSpec.describe Projects::HashedStorage::RollbackRepositoryService, :clean_gitlab_redis_shared_state, feature_category: :projects do let(:gitlab_shell) { Gitlab::Shell.new } let(:project) { create(:project, :repository, :wiki_repo, :design_repo, storage_version: ::Project::HASHED_STORAGE_FEATURES[:repository]) } let(:legacy_storage) { Storage::LegacyProject.new(project) } diff --git a/spec/services/projects/hashed_storage/rollback_service_spec.rb b/spec/services/projects/hashed_storage/rollback_service_spec.rb index 0bd63f2da2a..6d047f856ec 100644 --- a/spec/services/projects/hashed_storage/rollback_service_spec.rb +++ b/spec/services/projects/hashed_storage/rollback_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::HashedStorage::RollbackService do +RSpec.describe Projects::HashedStorage::RollbackService, feature_category: :projects do let(:project) { create(:project, :empty_repo, :wiki_repo) } let(:logger) { double } let!(:project_attachment) { build(:file_uploader, project: project) } diff --git a/spec/services/projects/import_error_filter_spec.rb b/spec/services/projects/import_error_filter_spec.rb index fd31cd52cc4..be07208c7f2 100644 --- a/spec/services/projects/import_error_filter_spec.rb +++ b/spec/services/projects/import_error_filter_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::ImportErrorFilter do +RSpec.describe Projects::ImportErrorFilter, feature_category: :importers do it 'filters any full paths' do message = 'Error importing into /my/folder Permission denied @ unlink_internal - /var/opt/gitlab/gitlab-rails/shared/a/b/c/uploads/file' diff --git a/spec/services/projects/import_export/relation_export_service_spec.rb b/spec/services/projects/import_export/relation_export_service_spec.rb index 94f5653ee7d..4b44a37b299 100644 --- a/spec/services/projects/import_export/relation_export_service_spec.rb +++ b/spec/services/projects/import_export/relation_export_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::ImportExport::RelationExportService do +RSpec.describe Projects::ImportExport::RelationExportService, feature_category: :importers do using RSpec::Parameterized::TableSyntax subject(:service) { described_class.new(relation_export, 'jid') } @@ -49,6 +49,7 @@ RSpec.describe Projects::ImportExport::RelationExportService do expect(logger).to receive(:error).with( export_error: '', message: 'Project relation export failed', + relation: relation_export.relation, project_export_job_id: project_export_job.id, project_id: project_export_job.project.id, project_name: project_export_job.project.name @@ -78,6 +79,7 @@ RSpec.describe Projects::ImportExport::RelationExportService do expect(logger).to receive(:error).with( export_error: 'Error!', message: 'Project relation export failed', + relation: relation_export.relation, project_export_job_id: project_export_job.id, project_id: project_export_job.project.id, project_name: project_export_job.project.name diff --git a/spec/services/projects/in_product_marketing_campaign_emails_service_spec.rb b/spec/services/projects/in_product_marketing_campaign_emails_service_spec.rb index 4c51c8a4ac8..4ad6fd0edff 100644 --- a/spec/services/projects/in_product_marketing_campaign_emails_service_spec.rb +++ b/spec/services/projects/in_product_marketing_campaign_emails_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::InProductMarketingCampaignEmailsService do +RSpec.describe Projects::InProductMarketingCampaignEmailsService, feature_category: :experimentation_adoption do describe '#execute' do let(:user) { create(:user, email_opted_in: true) } let(:project) { create(:project) } diff --git a/spec/services/projects/lfs_pointers/lfs_download_link_list_service_spec.rb b/spec/services/projects/lfs_pointers/lfs_download_link_list_service_spec.rb index 80b3c4d0403..0aaaae19f5a 100644 --- a/spec/services/projects/lfs_pointers/lfs_download_link_list_service_spec.rb +++ b/spec/services/projects/lfs_pointers/lfs_download_link_list_service_spec.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true require 'spec_helper' -RSpec.describe Projects::LfsPointers::LfsDownloadLinkListService do +RSpec.describe Projects::LfsPointers::LfsDownloadLinkListService, feature_category: :source_code_management do let(:import_url) { 'http://www.gitlab.com/demo/repo.git' } let(:lfs_endpoint) { "#{import_url}/info/lfs/objects/batch" } let!(:project) { create(:project, import_url: import_url) } diff --git a/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb b/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb index c815ad38843..00c156ba538 100644 --- a/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb +++ b/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true require 'spec_helper' -RSpec.describe Projects::LfsPointers::LfsDownloadService do +RSpec.describe Projects::LfsPointers::LfsDownloadService, feature_category: :source_code_management do include StubRequests let_it_be(:project) { create(:project) } diff --git a/spec/services/projects/lfs_pointers/lfs_import_service_spec.rb b/spec/services/projects/lfs_pointers/lfs_import_service_spec.rb index 32b86ade81e..f1e4db55962 100644 --- a/spec/services/projects/lfs_pointers/lfs_import_service_spec.rb +++ b/spec/services/projects/lfs_pointers/lfs_import_service_spec.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true require 'spec_helper' -RSpec.describe Projects::LfsPointers::LfsImportService do +RSpec.describe Projects::LfsPointers::LfsImportService, feature_category: :source_code_management do let(:project) { create(:project) } let(:user) { project.creator } let(:import_url) { 'http://www.gitlab.com/demo/repo.git' } diff --git a/spec/services/projects/lfs_pointers/lfs_link_service_spec.rb b/spec/services/projects/lfs_pointers/lfs_link_service_spec.rb index 0e7d16f18e8..fb3cc9bdac9 100644 --- a/spec/services/projects/lfs_pointers/lfs_link_service_spec.rb +++ b/spec/services/projects/lfs_pointers/lfs_link_service_spec.rb @@ -1,9 +1,10 @@ # frozen_string_literal: true require 'spec_helper' -RSpec.describe Projects::LfsPointers::LfsLinkService do - let!(:project) { create(:project, lfs_enabled: true) } - let!(:lfs_objects_project) { create_list(:lfs_objects_project, 2, project: project) } +RSpec.describe Projects::LfsPointers::LfsLinkService, feature_category: :source_code_management do + let_it_be(:project) { create(:project, lfs_enabled: true) } + let_it_be(:lfs_objects_project) { create_list(:lfs_objects_project, 2, project: project) } + let(:new_oids) { { 'oid1' => 123, 'oid2' => 125 } } let(:all_oids) { LfsObject.pluck(:oid, :size).to_h.merge(new_oids) } let(:new_lfs_object) { create(:lfs_object) } @@ -17,12 +18,26 @@ RSpec.describe Projects::LfsPointers::LfsLinkService do describe '#execute' do it 'raises an error when trying to link too many objects at once' do + stub_const("#{described_class}::MAX_OIDS", 5) + oids = Array.new(described_class::MAX_OIDS) { |i| "oid-#{i}" } oids << 'the straw' expect { subject.execute(oids) }.to raise_error(described_class::TooManyOidsError) end + it 'executes a block after validation and before execution' do + block = instance_double(Proc) + + expect(subject).to receive(:validate!).ordered + expect(block).to receive(:call).ordered + expect(subject).to receive(:link_existing_lfs_objects).ordered + + subject.execute([]) do + block.call + end + end + it 'links existing lfs objects to the project' do expect(project.lfs_objects.count).to eq 2 @@ -41,13 +56,13 @@ RSpec.describe Projects::LfsPointers::LfsLinkService do it 'links in batches' do stub_const("#{described_class}::BATCH_SIZE", 3) - expect(Gitlab::Import::Logger) - .to receive(:info) - .with(class: described_class.name, - project_id: project.id, - project_path: project.full_path, - lfs_objects_linked_count: 7, - iterations: 3) + expect(Gitlab::Import::Logger).to receive(:info).with( + class: described_class.name, + project_id: project.id, + project_path: project.full_path, + lfs_objects_linked_count: 7, + iterations: 3 + ) lfs_objects = create_list(:lfs_object, 7) linked = subject.execute(lfs_objects.pluck(:oid)) diff --git a/spec/services/projects/lfs_pointers/lfs_object_download_list_service_spec.rb b/spec/services/projects/lfs_pointers/lfs_object_download_list_service_spec.rb index 59eb1ed7a29..f5dcae05959 100644 --- a/spec/services/projects/lfs_pointers/lfs_object_download_list_service_spec.rb +++ b/spec/services/projects/lfs_pointers/lfs_object_download_list_service_spec.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true require 'spec_helper' -RSpec.describe Projects::LfsPointers::LfsObjectDownloadListService do +RSpec.describe Projects::LfsPointers::LfsObjectDownloadListService, feature_category: :source_code_management do let(:import_url) { 'http://www.gitlab.com/demo/repo.git' } let(:default_endpoint) { "#{import_url}/info/lfs/objects/batch" } let(:group) { create(:group, lfs_enabled: true) } diff --git a/spec/services/projects/move_access_service_spec.rb b/spec/services/projects/move_access_service_spec.rb index 45e10c3ca84..b9244002f6c 100644 --- a/spec/services/projects/move_access_service_spec.rb +++ b/spec/services/projects/move_access_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::MoveAccessService do +RSpec.describe Projects::MoveAccessService, feature_category: :projects do let(:user) { create(:user) } let(:group) { create(:group) } let(:project_with_access) { create(:project, namespace: user.namespace) } diff --git a/spec/services/projects/move_deploy_keys_projects_service_spec.rb b/spec/services/projects/move_deploy_keys_projects_service_spec.rb index 59674a3a4ef..b40eb4a18d1 100644 --- a/spec/services/projects/move_deploy_keys_projects_service_spec.rb +++ b/spec/services/projects/move_deploy_keys_projects_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::MoveDeployKeysProjectsService do +RSpec.describe Projects::MoveDeployKeysProjectsService, feature_category: :continuous_delivery do let!(:user) { create(:user) } let!(:project_with_deploy_keys) { create(:project, namespace: user.namespace) } let!(:target_project) { create(:project, namespace: user.namespace) } diff --git a/spec/services/projects/move_forks_service_spec.rb b/spec/services/projects/move_forks_service_spec.rb index 7d3637b7758..093562207dd 100644 --- a/spec/services/projects/move_forks_service_spec.rb +++ b/spec/services/projects/move_forks_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::MoveForksService do +RSpec.describe Projects::MoveForksService, feature_category: :source_code_management do include ProjectForksHelper let!(:user) { create(:user) } diff --git a/spec/services/projects/move_lfs_objects_projects_service_spec.rb b/spec/services/projects/move_lfs_objects_projects_service_spec.rb index e3df5fed9cf..f3cc4014b1c 100644 --- a/spec/services/projects/move_lfs_objects_projects_service_spec.rb +++ b/spec/services/projects/move_lfs_objects_projects_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::MoveLfsObjectsProjectsService do +RSpec.describe Projects::MoveLfsObjectsProjectsService, feature_category: :source_code_management do let!(:user) { create(:user) } let!(:project_with_lfs_objects) { create(:project, namespace: user.namespace) } let!(:target_project) { create(:project, namespace: user.namespace) } diff --git a/spec/services/projects/move_notification_settings_service_spec.rb b/spec/services/projects/move_notification_settings_service_spec.rb index e381ae7590f..5ef6e8a0647 100644 --- a/spec/services/projects/move_notification_settings_service_spec.rb +++ b/spec/services/projects/move_notification_settings_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::MoveNotificationSettingsService do +RSpec.describe Projects::MoveNotificationSettingsService, feature_category: :projects do let(:user) { create(:user) } let(:project_with_notifications) { create(:project, namespace: user.namespace) } let(:target_project) { create(:project, namespace: user.namespace) } diff --git a/spec/services/projects/move_project_authorizations_service_spec.rb b/spec/services/projects/move_project_authorizations_service_spec.rb index d47b13ca939..6cd0b056325 100644 --- a/spec/services/projects/move_project_authorizations_service_spec.rb +++ b/spec/services/projects/move_project_authorizations_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::MoveProjectAuthorizationsService do +RSpec.describe Projects::MoveProjectAuthorizationsService, feature_category: :projects do let!(:user) { create(:user) } let(:project_with_users) { create(:project, namespace: user.namespace) } let(:target_project) { create(:project, namespace: user.namespace) } diff --git a/spec/services/projects/move_project_group_links_service_spec.rb b/spec/services/projects/move_project_group_links_service_spec.rb index 1fca96a0367..cfd4b51b001 100644 --- a/spec/services/projects/move_project_group_links_service_spec.rb +++ b/spec/services/projects/move_project_group_links_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::MoveProjectGroupLinksService do +RSpec.describe Projects::MoveProjectGroupLinksService, feature_category: :projects do let!(:user) { create(:user) } let(:project_with_groups) { create(:project, namespace: user.namespace) } let(:target_project) { create(:project, namespace: user.namespace) } diff --git a/spec/services/projects/move_project_members_service_spec.rb b/spec/services/projects/move_project_members_service_spec.rb index 8fbd0ba3270..364fb7faaf2 100644 --- a/spec/services/projects/move_project_members_service_spec.rb +++ b/spec/services/projects/move_project_members_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::MoveProjectMembersService do +RSpec.describe Projects::MoveProjectMembersService, feature_category: :projects do let!(:user) { create(:user) } let(:project_with_users) { create(:project, namespace: user.namespace) } let(:target_project) { create(:project, namespace: user.namespace) } diff --git a/spec/services/projects/move_users_star_projects_service_spec.rb b/spec/services/projects/move_users_star_projects_service_spec.rb index b580d3d8772..b99e51d954b 100644 --- a/spec/services/projects/move_users_star_projects_service_spec.rb +++ b/spec/services/projects/move_users_star_projects_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::MoveUsersStarProjectsService do +RSpec.describe Projects::MoveUsersStarProjectsService, feature_category: :projects do let!(:user) { create(:user) } let!(:project_with_stars) { create(:project, namespace: user.namespace) } let!(:target_project) { create(:project, namespace: user.namespace) } diff --git a/spec/services/projects/open_issues_count_service_spec.rb b/spec/services/projects/open_issues_count_service_spec.rb index c739fea5ecf..89405f06f5d 100644 --- a/spec/services/projects/open_issues_count_service_spec.rb +++ b/spec/services/projects/open_issues_count_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::OpenIssuesCountService, :use_clean_rails_memory_store_caching do +RSpec.describe Projects::OpenIssuesCountService, :use_clean_rails_memory_store_caching, feature_category: :team_planning do let(:project) { create(:project) } subject { described_class.new(project) } diff --git a/spec/services/projects/open_merge_requests_count_service_spec.rb b/spec/services/projects/open_merge_requests_count_service_spec.rb index 6caef181e77..9d94fff2d20 100644 --- a/spec/services/projects/open_merge_requests_count_service_spec.rb +++ b/spec/services/projects/open_merge_requests_count_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::OpenMergeRequestsCountService, :use_clean_rails_memory_store_caching do +RSpec.describe Projects::OpenMergeRequestsCountService, :use_clean_rails_memory_store_caching, feature_category: :code_review_workflow do let_it_be(:project) { create(:project) } subject { described_class.new(project) } @@ -11,10 +11,7 @@ RSpec.describe Projects::OpenMergeRequestsCountService, :use_clean_rails_memory_ describe '#count' do it 'returns the number of open merge requests' do - create(:merge_request, - :opened, - source_project: project, - target_project: project) + create(:merge_request, :opened, source_project: project, target_project: project) expect(subject.count).to eq(1) end diff --git a/spec/services/projects/operations/update_service_spec.rb b/spec/services/projects/operations/update_service_spec.rb index 95f2176dbc0..7babaf4d0d8 100644 --- a/spec/services/projects/operations/update_service_spec.rb +++ b/spec/services/projects/operations/update_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::Operations::UpdateService do +RSpec.describe Projects::Operations::UpdateService, feature_category: :projects do let_it_be_with_refind(:project) { create(:project) } let_it_be(:user) { create(:user) } diff --git a/spec/services/projects/overwrite_project_service_spec.rb b/spec/services/projects/overwrite_project_service_spec.rb index 7038910508f..b4faf45a1cb 100644 --- a/spec/services/projects/overwrite_project_service_spec.rb +++ b/spec/services/projects/overwrite_project_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::OverwriteProjectService do +RSpec.describe Projects::OverwriteProjectService, feature_category: :projects do include ProjectForksHelper let(:user) { create(:user) } diff --git a/spec/services/projects/participants_service_spec.rb b/spec/services/projects/participants_service_spec.rb index fc745cd669f..bd297343879 100644 --- a/spec/services/projects/participants_service_spec.rb +++ b/spec/services/projects/participants_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::ParticipantsService do +RSpec.describe Projects::ParticipantsService, feature_category: :projects do describe '#execute' do let_it_be(:user) { create(:user) } let_it_be(:project) { create(:project, :public) } diff --git a/spec/services/projects/prometheus/alerts/notify_service_spec.rb b/spec/services/projects/prometheus/alerts/notify_service_spec.rb index 43d23023d83..0feac6c3e72 100644 --- a/spec/services/projects/prometheus/alerts/notify_service_spec.rb +++ b/spec/services/projects/prometheus/alerts/notify_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::Prometheus::Alerts::NotifyService do +RSpec.describe Projects::Prometheus::Alerts::NotifyService, feature_category: :metrics do include PrometheusHelpers using RSpec::Parameterized::TableSyntax @@ -45,10 +45,8 @@ RSpec.describe Projects::Prometheus::Alerts::NotifyService do end before do - create(:clusters_integrations_prometheus, - cluster: prd_cluster, alert_manager_token: token) - create(:clusters_integrations_prometheus, - cluster: stg_cluster, alert_manager_token: nil) + create(:clusters_integrations_prometheus, cluster: prd_cluster, alert_manager_token: token) + create(:clusters_integrations_prometheus, cluster: stg_cluster, alert_manager_token: nil) end context 'without token' do @@ -78,10 +76,12 @@ RSpec.describe Projects::Prometheus::Alerts::NotifyService do cluster.update!(enabled: cluster_enabled) unless integration_enabled.nil? - create(:clusters_integrations_prometheus, - cluster: cluster, - enabled: integration_enabled, - alert_manager_token: configured_token) + create( + :clusters_integrations_prometheus, + cluster: cluster, + enabled: integration_enabled, + alert_manager_token: configured_token + ) end end @@ -118,9 +118,11 @@ RSpec.describe Projects::Prometheus::Alerts::NotifyService do create(:prometheus_integration, project: project) if alerting_setting - create(:project_alerting_setting, - project: project, - token: configured_token) + create( + :project_alerting_setting, + project: project, + token: configured_token + ) end end diff --git a/spec/services/projects/prometheus/metrics/destroy_service_spec.rb b/spec/services/projects/prometheus/metrics/destroy_service_spec.rb index b4af81f2c87..4c2a959a149 100644 --- a/spec/services/projects/prometheus/metrics/destroy_service_spec.rb +++ b/spec/services/projects/prometheus/metrics/destroy_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::Prometheus::Metrics::DestroyService do +RSpec.describe Projects::Prometheus::Metrics::DestroyService, feature_category: :metrics do let(:metric) { create(:prometheus_metric) } subject { described_class.new(metric) } diff --git a/spec/services/projects/protect_default_branch_service_spec.rb b/spec/services/projects/protect_default_branch_service_spec.rb index 9f9e89ff8f8..a4fdd9983b8 100644 --- a/spec/services/projects/protect_default_branch_service_spec.rb +++ b/spec/services/projects/protect_default_branch_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::ProtectDefaultBranchService do +RSpec.describe Projects::ProtectDefaultBranchService, feature_category: :source_code_management do let(:service) { described_class.new(project) } let(:project) { create(:project) } @@ -247,6 +247,7 @@ RSpec.describe Projects::ProtectDefaultBranchService do context 'when feature flag `group_protected_branches` disabled' do before do stub_feature_flags(group_protected_branches: false) + stub_feature_flags(allow_protected_branches_for_group: false) end it 'return false' do @@ -257,6 +258,7 @@ RSpec.describe Projects::ProtectDefaultBranchService do context 'when feature flag `group_protected_branches` enabled' do before do stub_feature_flags(group_protected_branches: true) + stub_feature_flags(allow_protected_branches_for_group: true) end it 'return true' do diff --git a/spec/services/projects/readme_renderer_service_spec.rb b/spec/services/projects/readme_renderer_service_spec.rb index 14cdcf67640..842d75e82ee 100644 --- a/spec/services/projects/readme_renderer_service_spec.rb +++ b/spec/services/projects/readme_renderer_service_spec.rb @@ -2,14 +2,14 @@ require 'spec_helper' -RSpec.describe Projects::ReadmeRendererService, '#execute' do +RSpec.describe Projects::ReadmeRendererService, '#execute', feature_category: :projects do using RSpec::Parameterized::TableSyntax subject(:service) { described_class.new(project, nil, opts) } let_it_be(:project) { create(:project, title: 'My Project', description: '_custom_description_') } - let(:opts) { {} } + let(:opts) { { default_branch: 'master' } } it 'renders the an ERB readme template' do expect(service.execute).to start_with(<<~MARKDOWN) diff --git a/spec/services/projects/record_target_platforms_service_spec.rb b/spec/services/projects/record_target_platforms_service_spec.rb index 22ff325a62e..17aa7fd7009 100644 --- a/spec/services/projects/record_target_platforms_service_spec.rb +++ b/spec/services/projects/record_target_platforms_service_spec.rb @@ -2,41 +2,30 @@ require 'spec_helper' -RSpec.describe Projects::RecordTargetPlatformsService, '#execute' do +RSpec.describe Projects::RecordTargetPlatformsService, '#execute', feature_category: :projects do let_it_be(:project) { create(:project) } let(:detector_service) { Projects::AppleTargetPlatformDetectorService } subject(:execute) { described_class.new(project, detector_service).execute } - context 'when detector returns target platform values' do - let(:detector_result) { [:ios, :osx] } - let(:service_result) { detector_result.map(&:to_s) } + context 'when project is an XCode project' do + def project_setting + ProjectSetting.find_by_project_id(project.id) + end before do - double = instance_double(detector_service, execute: detector_result) - allow(detector_service).to receive(:new) { double } + double = instance_double(detector_service, execute: [:ios, :osx]) + allow(Projects::AppleTargetPlatformDetectorService).to receive(:new) { double } end - shared_examples 'saves and returns detected target platforms' do - it 'creates a new setting record for the project', :aggregate_failures do - expect { execute }.to change { ProjectSetting.count }.from(0).to(1) - expect(ProjectSetting.last.target_platforms).to match_array(service_result) - end - - it 'returns the array of stored target platforms' do - expect(execute).to match_array service_result - end + it 'creates a new setting record for the project', :aggregate_failures do + expect { execute }.to change { ProjectSetting.count }.from(0).to(1) + expect(ProjectSetting.last.target_platforms).to match_array(%w(ios osx)) end - it_behaves_like 'saves and returns detected target platforms' - - context 'when detector returns a non-array value' do - let(:detector_service) { Projects::AndroidTargetPlatformDetectorService } - let(:detector_result) { :android } - let(:service_result) { [detector_result.to_s] } - - it_behaves_like 'saves and returns detected target platforms' + it 'returns array of detected target platforms' do + expect(execute).to match_array %w(ios osx) end context 'when a project has an existing setting record' do @@ -44,10 +33,6 @@ RSpec.describe Projects::RecordTargetPlatformsService, '#execute' do create(:project_setting, project: project, target_platforms: saved_target_platforms) end - def project_setting - ProjectSetting.find_by_project_id(project.id) - end - context 'when target platforms changed' do let(:saved_target_platforms) { %w(tvos) } @@ -98,44 +83,23 @@ RSpec.describe Projects::RecordTargetPlatformsService, '#execute' do it_behaves_like 'tracks experiment assignment event' end - shared_examples 'does not send email' do - it 'does not execute a Projects::InProductMarketingCampaignEmailsService' do - expect(Projects::InProductMarketingCampaignEmailsService).not_to receive(:new) - - execute - end - end - context 'experiment control' do before do stub_experiments(build_ios_app_guide_email: :control) end - it_behaves_like 'does not send email' - it_behaves_like 'tracks experiment assignment event' - end - - context 'when project is not an iOS project' do - let(:detector_service) { Projects::AppleTargetPlatformDetectorService } - let(:detector_result) { :android } - - before do - stub_experiments(build_ios_app_guide_email: :candidate) - end - - it_behaves_like 'does not send email' - - it 'does not track experiment assignment event', :experiment do - expect(experiment(:build_ios_app_guide_email)) - .not_to track(:assignment) + it 'does not execute a Projects::InProductMarketingCampaignEmailsService' do + expect(Projects::InProductMarketingCampaignEmailsService).not_to receive(:new) execute end + + it_behaves_like 'tracks experiment assignment event' end end end - context 'when detector does not return any target platform values' do + context 'when project is not an XCode project' do before do double = instance_double(Projects::AppleTargetPlatformDetectorService, execute: []) allow(Projects::AppleTargetPlatformDetectorService).to receive(:new).with(project) { double } diff --git a/spec/services/projects/refresh_build_artifacts_size_statistics_service_spec.rb b/spec/services/projects/refresh_build_artifacts_size_statistics_service_spec.rb index 62330441d2f..591cd1cba8d 100644 --- a/spec/services/projects/refresh_build_artifacts_size_statistics_service_spec.rb +++ b/spec/services/projects/refresh_build_artifacts_size_statistics_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::RefreshBuildArtifactsSizeStatisticsService, :clean_gitlab_redis_shared_state do +RSpec.describe Projects::RefreshBuildArtifactsSizeStatisticsService, :clean_gitlab_redis_shared_state, feature_category: :build_artifacts do let(:service) { described_class.new } describe '#execute' do diff --git a/spec/services/projects/repository_languages_service_spec.rb b/spec/services/projects/repository_languages_service_spec.rb index 50d5fba6b84..a02844309b2 100644 --- a/spec/services/projects/repository_languages_service_spec.rb +++ b/spec/services/projects/repository_languages_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::RepositoryLanguagesService do +RSpec.describe Projects::RepositoryLanguagesService, feature_category: :source_code_management do let(:service) { described_class.new(project, project.first_owner) } context 'when detected_repository_languages flag is set' do diff --git a/spec/services/projects/schedule_bulk_repository_shard_moves_service_spec.rb b/spec/services/projects/schedule_bulk_repository_shard_moves_service_spec.rb index 76830396104..3d89f6efa6f 100644 --- a/spec/services/projects/schedule_bulk_repository_shard_moves_service_spec.rb +++ b/spec/services/projects/schedule_bulk_repository_shard_moves_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::ScheduleBulkRepositoryShardMovesService do +RSpec.describe Projects::ScheduleBulkRepositoryShardMovesService, feature_category: :source_code_management do it_behaves_like 'moves repository shard in bulk' do let_it_be_with_reload(:container) { create(:project, :repository) } diff --git a/spec/services/projects/transfer_service_spec.rb b/spec/services/projects/transfer_service_spec.rb index 32818535146..48d5935f22f 100644 --- a/spec/services/projects/transfer_service_spec.rb +++ b/spec/services/projects/transfer_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::TransferService do +RSpec.describe Projects::TransferService, feature_category: :projects do let_it_be(:group) { create(:group) } let_it_be(:user) { create(:user) } let_it_be(:group_integration) { create(:integrations_slack, :group, group: group, webhook: 'http://group.slack.com') } @@ -20,12 +20,32 @@ RSpec.describe Projects::TransferService do subject(:transfer_service) { described_class.new(project, user) } - let!(:package) { create(:npm_package, project: project) } + let!(:package) { create(:npm_package, project: project, name: "@testscope/test") } context 'with a root namespace change' do + it 'allow the transfer' do + expect(transfer_service.execute(group)).to be true + expect(project.errors[:new_namespace]).to be_empty + end + end + + context 'with pending destruction package' do + before do + package.pending_destruction! + end + + it 'allow the transfer' do + expect(transfer_service.execute(group)).to be true + expect(project.errors[:new_namespace]).to be_empty + end + end + + context 'with namespaced packages present' do + let!(:package) { create(:npm_package, project: project, name: "@#{project.root_namespace.path}/test") } + it 'does not allow the transfer' do expect(transfer_service.execute(group)).to be false - expect(project.errors[:new_namespace]).to include("Root namespace can't be updated if project has NPM packages") + expect(project.errors[:new_namespace]).to include("Root namespace can't be updated if the project has NPM packages scoped to the current root level namespace.") end end @@ -39,7 +59,7 @@ RSpec.describe Projects::TransferService do other_group.add_owner(user) end - it 'does allow the transfer' do + it 'allow the transfer' do expect(transfer_service.execute(other_group)).to be true expect(project.errors[:new_namespace]).to be_empty end @@ -667,10 +687,11 @@ RSpec.describe Projects::TransferService do user_ids = [user.id, member_of_old_group.id, member_of_new_group.id].map { |id| [id] } expect(AuthorizedProjectUpdate::UserRefreshFromReplicaWorker).to( - receive(:bulk_perform_in) - .with(1.hour, - user_ids, - batch_delay: 30.seconds, batch_size: 100) + receive(:bulk_perform_in).with( + 1.hour, + user_ids, + batch_delay: 30.seconds, batch_size: 100 + ) ) subject @@ -694,10 +715,15 @@ RSpec.describe Projects::TransferService do project.design_repository end + def clear_design_repo_memoization + project.design_management_repository.clear_memoization(:repository) + project.clear_memoization(:design_repository) + end + it 'does not create a design repository' do expect(subject.execute(group)).to be true - project.clear_memoization(:design_repository) + clear_design_repo_memoization expect(design_repository.exists?).to be false end @@ -713,7 +739,7 @@ RSpec.describe Projects::TransferService do it 'moves the repository' do expect(subject.execute(group)).to be true - project.clear_memoization(:design_repository) + clear_design_repo_memoization expect(design_repository).to have_attributes( disk_path: new_full_path, @@ -725,7 +751,7 @@ RSpec.describe Projects::TransferService do allow(subject).to receive(:execute_system_hooks).and_raise('foo') expect { subject.execute(group) }.to raise_error('foo') - project.clear_memoization(:design_repository) + clear_design_repo_memoization expect(design_repository).to have_attributes( disk_path: old_full_path, @@ -742,7 +768,7 @@ RSpec.describe Projects::TransferService do expect(subject.execute(group)).to be true - project.clear_memoization(:design_repository) + clear_design_repo_memoization expect(design_repository).to have_attributes( disk_path: old_disk_path, @@ -756,7 +782,7 @@ RSpec.describe Projects::TransferService do allow(subject).to receive(:execute_system_hooks).and_raise('foo') expect { subject.execute(group) }.to raise_error('foo') - project.clear_memoization(:design_repository) + clear_design_repo_memoization expect(design_repository).to have_attributes( disk_path: old_disk_path, diff --git a/spec/services/projects/unlink_fork_service_spec.rb b/spec/services/projects/unlink_fork_service_spec.rb index d939a79b7e9..872e38aba1d 100644 --- a/spec/services/projects/unlink_fork_service_spec.rb +++ b/spec/services/projects/unlink_fork_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::UnlinkForkService, :use_clean_rails_memory_store_caching do +RSpec.describe Projects::UnlinkForkService, :use_clean_rails_memory_store_caching, feature_category: :source_code_management do include ProjectForksHelper subject { described_class.new(forked_project, user) } @@ -116,8 +116,10 @@ RSpec.describe Projects::UnlinkForkService, :use_clean_rails_memory_store_cachin expect(project.fork_network_member).to be_nil expect(project.fork_network).to be_nil - expect(forked_project.fork_network).to have_attributes(root_project_id: nil, - deleted_root_project_name: project.full_name) + expect(forked_project.fork_network).to have_attributes( + root_project_id: nil, + deleted_root_project_name: project.full_name + ) expect(project.forked_to_members.count).to eq(0) expect(forked_project.forked_to_members.count).to eq(1) expect(fork_of_fork.forked_to_members.count).to eq(0) diff --git a/spec/services/projects/update_pages_service_spec.rb b/spec/services/projects/update_pages_service_spec.rb index d908a169898..a97369c4b08 100644 --- a/spec/services/projects/update_pages_service_spec.rb +++ b/spec/services/projects/update_pages_service_spec.rb @@ -2,19 +2,22 @@ require "spec_helper" -RSpec.describe Projects::UpdatePagesService do +RSpec.describe Projects::UpdatePagesService, feature_category: :pages do let_it_be(:project, refind: true) { create(:project, :repository) } let_it_be(:old_pipeline) { create(:ci_pipeline, project: project, sha: project.commit('HEAD').sha) } let_it_be(:pipeline) { create(:ci_pipeline, project: project, sha: project.commit('HEAD').sha) } - let(:build) { create(:ci_build, pipeline: pipeline, ref: 'HEAD') } + let(:options) { {} } + let(:build) { create(:ci_build, pipeline: pipeline, ref: 'HEAD', options: options) } let(:invalid_file) { fixture_file_upload('spec/fixtures/dk.png') } let(:file) { fixture_file_upload("spec/fixtures/pages.zip") } + let(:custom_root_file) { fixture_file_upload("spec/fixtures/pages_with_custom_root.zip") } let(:empty_file) { fixture_file_upload("spec/fixtures/pages_empty.zip") } let(:empty_metadata_filename) { "spec/fixtures/pages_empty.zip.meta" } let(:metadata_filename) { "spec/fixtures/pages.zip.meta" } + let(:custom_root_file_metadata) { "spec/fixtures/pages_with_custom_root.zip.meta" } let(:metadata) { fixture_file_upload(metadata_filename) if File.exist?(metadata_filename) } subject { described_class.new(project, build) } @@ -97,6 +100,7 @@ RSpec.describe Projects::UpdatePagesService do expect(deployment.file_sha256).to eq(artifacts_archive.file_sha256) expect(project.pages_metadatum.reload.pages_deployment_id).to eq(deployment.id) expect(deployment.ci_build_id).to eq(build.id) + expect(deployment.root_directory).to be_nil end it 'does not fail if pages_metadata is absent' do @@ -116,9 +120,11 @@ RSpec.describe Projects::UpdatePagesService do it 'schedules a destruction of older deployments' do expect(DestroyPagesDeploymentsWorker).to( - receive(:perform_in).with(described_class::OLD_DEPLOYMENTS_DESTRUCTION_DELAY, - project.id, - instance_of(Integer)) + receive(:perform_in).with( + described_class::OLD_DEPLOYMENTS_DESTRUCTION_DELAY, + project.id, + instance_of(Integer) + ) ) execute @@ -140,7 +146,45 @@ RSpec.describe Projects::UpdatePagesService do it 'returns an error' do expect(execute).not_to eq(:success) - expect(GenericCommitStatus.last.description).to eq("Error: The `public/` folder is missing, or not declared in `.gitlab-ci.yml`.") + expect(GenericCommitStatus.last.description).to eq("Error: You need to either include a `public/` folder in your artifacts, or specify which one to use for Pages using `publish` in `.gitlab-ci.yml`") + end + end + + context 'when there is a custom root config' do + let(:file) { custom_root_file } + let(:metadata_filename) { custom_root_file_metadata } + + context 'when the directory specified with `publish` is included in the artifacts' do + let(:options) { { publish: 'foo' } } + + it 'creates pages_deployment and saves it in the metadata' do + expect(execute).to eq(:success) + + deployment = project.pages_deployments.last + expect(deployment.root_directory).to eq(options[:publish]) + end + end + + context 'when the directory specified with `publish` is not included in the artifacts' do + let(:options) { { publish: 'bar' } } + + it 'returns an error' do + expect(execute).not_to eq(:success) + + expect(GenericCommitStatus.last.description).to eq("Error: You need to either include a `public/` folder in your artifacts, or specify which one to use for Pages using `publish` in `.gitlab-ci.yml`") + end + end + + context 'when there is a folder named `public`, but `publish` specifies a different one' do + let(:options) { { publish: 'foo' } } + let(:file) { fixture_file_upload("spec/fixtures/pages.zip") } + let(:metadata_filename) { "spec/fixtures/pages.zip.meta" } + + it 'returns an error' do + expect(execute).not_to eq(:success) + + expect(GenericCommitStatus.last.description).to eq("Error: You need to either include a `public/` folder in your artifacts, or specify which one to use for Pages using `publish` in `.gitlab-ci.yml`") + end end end @@ -322,10 +366,14 @@ RSpec.describe Projects::UpdatePagesService do context 'when retrying the job' do let(:stage) { create(:ci_stage, position: 1_000_000, name: 'deploy', pipeline: pipeline) } let!(:older_deploy_job) do - create(:generic_commit_status, :failed, pipeline: pipeline, - ref: build.ref, - ci_stage: stage, - name: 'pages:deploy') + create( + :generic_commit_status, + :failed, + pipeline: pipeline, + ref: build.ref, + ci_stage: stage, + name: 'pages:deploy' + ) end before do diff --git a/spec/services/projects/update_remote_mirror_service_spec.rb b/spec/services/projects/update_remote_mirror_service_spec.rb index 547641867bc..b65f7a50e4c 100644 --- a/spec/services/projects/update_remote_mirror_service_spec.rb +++ b/spec/services/projects/update_remote_mirror_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::UpdateRemoteMirrorService do +RSpec.describe Projects::UpdateRemoteMirrorService, feature_category: :source_code_management do let_it_be(:project) { create(:project, :repository, lfs_enabled: true) } let_it_be(:remote_project) { create(:forked_project_with_submodules) } let_it_be(:remote_mirror) { create(:remote_mirror, project: project, enabled: true) } diff --git a/spec/services/projects/update_repository_storage_service_spec.rb b/spec/services/projects/update_repository_storage_service_spec.rb index ee8f7fb2ef2..af920d51776 100644 --- a/spec/services/projects/update_repository_storage_service_spec.rb +++ b/spec/services/projects/update_repository_storage_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::UpdateRepositoryStorageService do +RSpec.describe Projects::UpdateRepositoryStorageService, feature_category: :source_code_management do include Gitlab::ShellAdapter subject { described_class.new(repository_storage_move) } diff --git a/spec/services/projects/update_service_spec.rb b/spec/services/projects/update_service_spec.rb index 3cda6bc2627..8f55ee705ab 100644 --- a/spec/services/projects/update_service_spec.rb +++ b/spec/services/projects/update_service_spec.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true require 'spec_helper' -RSpec.describe Projects::UpdateService do +RSpec.describe Projects::UpdateService, feature_category: :projects do include ExternalAuthorizationServiceHelpers include ProjectForksHelper @@ -227,48 +227,16 @@ RSpec.describe Projects::UpdateService do let(:user) { project.first_owner } let(:forked_project) { fork_project(project) } - context 'and unlink forks feature flag is off' do - before do - stub_feature_flags(unlink_fork_network_upon_visibility_decrease: false) - end - - it 'updates forks visibility level when parent set to more restrictive' do - opts = { visibility_level: Gitlab::VisibilityLevel::PRIVATE } - - expect(project).to be_internal - expect(forked_project).to be_internal - - expect(update_project(project, user, opts)).to eq({ status: :success }) + it 'does not change visibility of forks' do + opts = { visibility_level: Gitlab::VisibilityLevel::PRIVATE } - expect(project).to be_private - expect(forked_project.reload).to be_private - end - - it 'does not update forks visibility level when parent set to less restrictive' do - opts = { visibility_level: Gitlab::VisibilityLevel::PUBLIC } - - expect(project).to be_internal - expect(forked_project).to be_internal + expect(project).to be_internal + expect(forked_project).to be_internal - expect(update_project(project, user, opts)).to eq({ status: :success }) + expect(update_project(project, user, opts)).to eq({ status: :success }) - expect(project).to be_public - expect(forked_project.reload).to be_internal - end - end - - context 'and unlink forks feature flag is on' do - it 'does not change visibility of forks' do - opts = { visibility_level: Gitlab::VisibilityLevel::PRIVATE } - - expect(project).to be_internal - expect(forked_project).to be_internal - - expect(update_project(project, user, opts)).to eq({ status: :success }) - - expect(project).to be_private - expect(forked_project.reload).to be_internal - end + expect(project).to be_private + expect(forked_project.reload).to be_internal end end @@ -358,7 +326,9 @@ RSpec.describe Projects::UpdateService do it 'logs an error and creates a metric when wiki can not be created' do project.project_feature.update!(wiki_access_level: ProjectFeature::DISABLED) - expect_any_instance_of(ProjectWiki).to receive(:create_wiki_repository).and_raise(Wiki::CouldNotCreateWikiError) + expect_next_instance_of(ProjectWiki) do |project_wiki| + expect(project_wiki).to receive(:create_wiki_repository).and_raise(Wiki::CouldNotCreateWikiError) + end expect_any_instance_of(described_class).to receive(:log_error).with("Could not create wiki for #{project.full_name}") counter = double(:counter) @@ -387,24 +357,26 @@ RSpec.describe Projects::UpdateService do # Using some sample features for testing. # Not using all the features because some of them must be enabled/disabled together %w[issues wiki forking].each do |feature_name| - let(:feature) { "#{feature_name}_access_level" } - let(:params) do - { project_feature_attributes: { feature => ProjectFeature::ENABLED } } - end + context "with feature_name:#{feature_name}" do + let(:feature) { "#{feature_name}_access_level" } + let(:params) do + { project_feature_attributes: { feature => ProjectFeature::ENABLED } } + end - before do - project.project_feature.update!(feature => ProjectFeature::DISABLED) - end + before do + project.project_feature.update!(feature => ProjectFeature::DISABLED) + end - it 'publishes Projects::ProjectFeaturesChangedEvent' do - expect { update_project(project, user, params) } - .to publish_event(Projects::ProjectFeaturesChangedEvent) - .with( - project_id: project.id, - namespace_id: project.namespace_id, - root_namespace_id: project.root_namespace.id, - features: ["updated_at", feature] - ) + it 'publishes Projects::ProjectFeaturesChangedEvent' do + expect { update_project(project, user, params) } + .to publish_event(Projects::ProjectFeaturesChangedEvent) + .with( + project_id: project.id, + namespace_id: project.namespace_id, + root_namespace_id: project.root_namespace.id, + features: array_including(feature, "updated_at") + ) + end end end end @@ -548,6 +520,25 @@ RSpec.describe Projects::UpdateService do end end + context 'when updating #runner_registration_enabled' do + it 'updates the attribute' do + expect { update_project(project, user, runner_registration_enabled: false) } + .to change { project.runner_registration_enabled } + .to(false) + end + + context 'when runner registration is disabled for all projects' do + before do + stub_application_setting(valid_runner_registrars: []) + end + + it 'restricts updating the attribute' do + expect { update_project(project, user, runner_registration_enabled: false) } + .not_to change { project.runner_registration_enabled } + end + end + end + context 'when updating runners settings' do let(:settings) do { instance_runners_enabled: true, namespace_traversal_ids: [123] } @@ -653,17 +644,19 @@ RSpec.describe Projects::UpdateService do context 'when updating nested attributes for prometheus integration' do context 'prometheus integration exists' do let(:prometheus_integration_attributes) do - attributes_for(:prometheus_integration, - project: project, - properties: { api_url: "http://new.prometheus.com", manual_configuration: "0" } - ) + attributes_for( + :prometheus_integration, + project: project, + properties: { api_url: "http://new.prometheus.com", manual_configuration: "0" } + ) end let!(:prometheus_integration) do - create(:prometheus_integration, - project: project, - properties: { api_url: "http://old.prometheus.com", manual_configuration: "0" } - ) + create( + :prometheus_integration, + project: project, + properties: { api_url: "http://old.prometheus.com", manual_configuration: "0" } + ) end it 'updates existing record' do @@ -677,10 +670,11 @@ RSpec.describe Projects::UpdateService do context 'prometheus integration does not exist' do context 'valid parameters' do let(:prometheus_integration_attributes) do - attributes_for(:prometheus_integration, - project: project, - properties: { api_url: "http://example.prometheus.com", manual_configuration: "0" } - ) + attributes_for( + :prometheus_integration, + project: project, + properties: { api_url: "http://example.prometheus.com", manual_configuration: "0" } + ) end it 'creates new record' do @@ -693,10 +687,11 @@ RSpec.describe Projects::UpdateService do context 'invalid parameters' do let(:prometheus_integration_attributes) do - attributes_for(:prometheus_integration, - project: project, - properties: { api_url: nil, manual_configuration: "1" } - ) + attributes_for( + :prometheus_integration, + project: project, + properties: { api_url: nil, manual_configuration: "1" } + ) end it 'does not create new record' do @@ -794,6 +789,112 @@ RSpec.describe Projects::UpdateService do expect(project.topic_list).to eq(%w[tag_list]) end end + + describe 'when updating pages unique domain', feature_category: :pages do + let(:group) { create(:group, path: 'group') } + let(:project) { create(:project, path: 'project', group: group) } + + context 'with pages_unique_domain feature flag disabled' do + before do + stub_feature_flags(pages_unique_domain: false) + end + + it 'does not change pages unique domain' do + expect(project) + .to receive(:update) + .with({ project_setting_attributes: { has_confluence: true } }) + .and_call_original + + expect do + update_project(project, user, project_setting_attributes: { + has_confluence: true, + pages_unique_domain_enabled: true + }) + end.not_to change { project.project_setting.pages_unique_domain_enabled } + end + + it 'does not remove other attributes' do + expect(project) + .to receive(:update) + .with({ name: 'True' }) + .and_call_original + + update_project(project, user, name: 'True') + end + end + + context 'with pages_unique_domain feature flag enabled' do + before do + stub_feature_flags(pages_unique_domain: true) + end + + it 'updates project pages unique domain' do + expect do + update_project(project, user, project_setting_attributes: { + pages_unique_domain_enabled: true + }) + end.to change { project.project_setting.pages_unique_domain_enabled } + + expect(project.project_setting.pages_unique_domain_enabled).to eq true + expect(project.project_setting.pages_unique_domain).to match %r{project-group-\w+} + end + + it 'does not changes unique domain when it already exists' do + project.project_setting.update!( + pages_unique_domain_enabled: false, + pages_unique_domain: 'unique-domain' + ) + + expect do + update_project(project, user, project_setting_attributes: { + pages_unique_domain_enabled: true + }) + end.to change { project.project_setting.pages_unique_domain_enabled } + + expect(project.project_setting.pages_unique_domain_enabled).to eq true + expect(project.project_setting.pages_unique_domain).to eq 'unique-domain' + end + + it 'does not changes unique domain when it disabling unique domain' do + project.project_setting.update!( + pages_unique_domain_enabled: true, + pages_unique_domain: 'unique-domain' + ) + + expect do + update_project(project, user, project_setting_attributes: { + pages_unique_domain_enabled: false + }) + end.not_to change { project.project_setting.pages_unique_domain } + + expect(project.project_setting.pages_unique_domain_enabled).to eq false + expect(project.project_setting.pages_unique_domain).to eq 'unique-domain' + end + + context 'when there is another project with the unique domain' do + it 'fails pages unique domain already exists' do + create( + :project_setting, + pages_unique_domain_enabled: true, + pages_unique_domain: 'unique-domain' + ) + + allow(Gitlab::Pages::RandomDomain) + .to receive(:generate) + .and_return('unique-domain') + + result = update_project(project, user, project_setting_attributes: { + pages_unique_domain_enabled: true + }) + + expect(result).to eq( + status: :error, + message: 'Project setting pages unique domain has already been taken' + ) + end + end + end + end end describe '#run_auto_devops_pipeline?' do diff --git a/spec/services/projects/update_statistics_service_spec.rb b/spec/services/projects/update_statistics_service_spec.rb index 1cc69e7e2fe..f685b86acc0 100644 --- a/spec/services/projects/update_statistics_service_spec.rb +++ b/spec/services/projects/update_statistics_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::UpdateStatisticsService do +RSpec.describe Projects::UpdateStatisticsService, feature_category: :projects do using RSpec::Parameterized::TableSyntax let(:service) { described_class.new(project, nil, statistics: statistics) } @@ -27,7 +27,7 @@ RSpec.describe Projects::UpdateStatisticsService do ['repository_size'] | [:size] [:repository_size] | [:size] [:lfs_objects_size] | nil - [:commit_count] | [:commit_count] # rubocop:disable Lint/BinaryOperatorWithIdenticalOperands + [:commit_count] | [:commit_count] [:repository_size, :commit_count] | %i(size commit_count) [:repository_size, :commit_count, :lfs_objects_size] | %i(size commit_count) end |