Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-05-15 12:08:57 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-05-15 12:08:57 +0300
commit45a8c43afe8a17de19a92708b380b29b6ae04ce6 (patch)
tree4104e6ac741fbbdeefe9b8b699650a06c14e9056 /spec
parent6bc327a3491069240bd73cc83e17b3078c4148b0 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/groups/milestones_controller_spec.rb15
-rw-r--r--spec/controllers/projects/milestones_controller_spec.rb21
-rw-r--r--spec/factories/container_registry/data_repair_detail.rb20
-rw-r--r--spec/features/groups/milestones/milestone_editing_spec.rb18
-rw-r--r--spec/features/issues/user_edits_issue_spec.rb14
-rw-r--r--spec/features/merge_request/user_edits_mr_spec.rb12
-rw-r--r--spec/features/projects/blobs/blob_show_spec.rb13
-rw-r--r--spec/features/projects/integrations/user_activates_mattermost_slash_command_spec.rb4
-rw-r--r--spec/features/projects/milestones/milestone_editing_spec.rb18
-rw-r--r--spec/finders/template_finder_spec.rb14
-rw-r--r--spec/frontend/ci/pipeline_editor/components/job_assistant_drawer/accordion_items/image_item_spec.js8
-rw-r--r--spec/frontend/ci/pipeline_editor/components/job_assistant_drawer/accordion_items/services_item_spec.js2
-rw-r--r--spec/graphql/resolvers/metrics/dashboards/annotation_resolver_spec.rb16
-rw-r--r--spec/graphql/types/permission_types/issue_spec.rb2
-rw-r--r--spec/graphql/types/project_statistics_redirect_type_spec.rb10
-rw-r--r--spec/graphql/types/project_type_spec.rb2
-rw-r--r--spec/helpers/projects_helper_spec.rb28
-rw-r--r--spec/lib/api/entities/package_spec.rb9
-rw-r--r--spec/lib/container_registry/gitlab_api_client_spec.rb155
-rw-r--r--spec/lib/gitlab/background_migration/backfill_cluster_agents_has_vulnerabilities_spec.rb10
-rw-r--r--spec/lib/gitlab/background_migration/backfill_environment_tiers_spec.rb10
-rw-r--r--spec/lib/gitlab/background_migration/backfill_group_features_spec.rb18
-rw-r--r--spec/lib/gitlab/background_migration/backfill_imported_issue_search_data_spec.rb16
-rw-r--r--spec/lib/gitlab/background_migration/backfill_namespace_details_spec.rb43
-rw-r--r--spec/lib/gitlab/background_migration/backfill_namespace_id_for_namespace_route_spec.rb35
-rw-r--r--spec/lib/gitlab/background_migration/backfill_namespace_id_of_vulnerability_reads_spec.rb17
-rw-r--r--spec/lib/gitlab/background_migration/backfill_project_feature_package_registry_access_level_spec.rb17
-rw-r--r--spec/lib/gitlab/background_migration/backfill_project_member_namespace_id_spec.rb70
-rw-r--r--spec/lib/gitlab/background_migration/backfill_project_namespace_details_spec.rb47
-rw-r--r--spec/lib/gitlab/background_migration/backfill_releases_author_id_spec.rb59
-rw-r--r--spec/lib/gitlab/background_migration/backfill_snippet_repositories_spec.rb66
-rw-r--r--spec/lib/gitlab/background_migration/backfill_vulnerability_reads_cluster_agent_spec.rb10
-rw-r--r--spec/lib/gitlab/background_migration/nullify_orphan_runner_id_on_ci_builds_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/prune_stale_project_export_jobs_spec.rb17
-rw-r--r--spec/lib/gitlab/background_migration/remove_backfilled_job_artifacts_expire_at_spec.rb6
-rw-r--r--spec/lib/gitlab/background_migration/remove_occurrence_pipelines_and_duplicate_vulnerabilities_findings_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/remove_self_managed_wiki_notes_spec.rb17
-rw-r--r--spec/lib/gitlab/background_migration/reset_too_many_tags_skipped_registry_imports_spec.rb72
-rw-r--r--spec/lib/gitlab/background_migration/set_correct_vulnerability_state_spec.rb16
-rw-r--r--spec/lib/gitlab/background_migration/set_legacy_open_source_license_available_for_non_public_projects_spec.rb33
-rw-r--r--spec/lib/gitlab/background_migration/update_delayed_project_removal_to_null_for_user_namespaces_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/update_jira_tracker_data_deployment_type_based_on_url_spec.rb10
-rw-r--r--spec/lib/gitlab/data_builder/deployment_spec.rb3
-rw-r--r--spec/lib/gitlab/database/migrations/instrumentation_spec.rb19
-rw-r--r--spec/lib/gitlab/database/schema_validation/inconsistency_spec.rb26
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml1
-rw-r--r--spec/models/blob_viewer/metrics_dashboard_yml_spec.rb16
-rw-r--r--spec/models/commit_spec.rb90
-rw-r--r--spec/models/container_registry/data_repair_detail_spec.rb18
-rw-r--r--spec/models/milestone_spec.rb8
-rw-r--r--spec/models/project_spec.rb14
-rw-r--r--spec/requests/api/graphql/metrics/dashboard/annotations_spec.rb17
-rw-r--r--spec/requests/api/graphql/mutations/metrics/dashboard/annotations/create_spec.rb13
-rw-r--r--spec/requests/api/graphql/mutations/metrics/dashboard/annotations/delete_spec.rb13
-rw-r--r--spec/requests/api/graphql/project/branches_tipping_at_commit_spec.rb67
-rw-r--r--spec/requests/api/graphql/project/commit_references_spec.rb240
-rw-r--r--spec/requests/api/graphql/project/project_statistics_redirect_spec.rb78
-rw-r--r--spec/requests/api/graphql/project/tags_tipping_at_commit_spec.rb67
-rw-r--r--spec/requests/api/metrics/dashboard/annotations_spec.rb13
-rw-r--r--spec/requests/api/project_packages_spec.rb12
-rw-r--r--spec/requests/api/project_templates_spec.rb25
-rw-r--r--spec/services/jira_connect/sync_service_spec.rb10
-rw-r--r--spec/support/import_export/export_file_helper.rb22
-rw-r--r--spec/support/shared_examples/controllers/snippets_sort_order_shared_examples.rb10
-rw-r--r--spec/support/shared_examples/controllers/wiki_actions_shared_examples.rb23
-rw-r--r--spec/support/shared_examples/features/editable_merge_request_shared_examples.rb12
-rw-r--r--spec/support/shared_examples/features/milestone_editing_shared_examples.rb21
-rw-r--r--spec/support/shared_examples/features/search/redacted_search_results_shared_examples.rb202
-rw-r--r--spec/support/shared_examples/features/wiki/user_views_wiki_page_shared_examples.rb8
-rw-r--r--spec/support/shared_examples/graphql/members_shared_examples.rb12
-rw-r--r--spec/support/shared_examples/graphql/mutation_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/graphql/mutations/set_assignees_shared_examples.rb10
-rw-r--r--spec/support/shared_examples/graphql/notes_on_noteables_shared_examples.rb8
-rw-r--r--spec/support/shared_examples/requests/api/container_repositories_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/requests/api/custom_attributes_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/requests/api/graphql/packages/group_and_project_packages_list_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/requests/api/graphql/packages/package_details_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/requests/api/labels_api_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/requests/api/milestones_shared_examples.rb8
-rw-r--r--spec/support/shared_examples/requests/api/notes_shared_examples.rb12
-rw-r--r--spec/support/shared_examples/requests/api/repository_storage_moves_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/services/packages_shared_examples.rb18
-rw-r--r--spec/workers/container_registry/cleanup_worker_spec.rb71
-rw-r--r--spec/workers/container_registry/record_data_repair_detail_worker_spec.rb191
-rw-r--r--spec/workers/every_sidekiq_worker_spec.rb1
85 files changed, 1788 insertions, 587 deletions
diff --git a/spec/controllers/groups/milestones_controller_spec.rb b/spec/controllers/groups/milestones_controller_spec.rb
index f4046cb97a0..87030448b30 100644
--- a/spec/controllers/groups/milestones_controller_spec.rb
+++ b/spec/controllers/groups/milestones_controller_spec.rb
@@ -260,6 +260,21 @@ RSpec.describe Groups::MilestonesController do
expect(response).to redirect_to(group_milestone_path(group, milestone.iid))
expect(milestone.title).to eq("title changed")
end
+
+ it "handles ActiveRecord::StaleObjectError" do
+ milestone_params[:title] = "title changed"
+ # Purposely reduce the lock_version to trigger an ActiveRecord::StaleObjectError
+ milestone_params[:lock_version] = milestone.lock_version - 1
+
+ put :update, params: {
+ id: milestone.iid,
+ group_id: group.to_param,
+ milestone: milestone_params
+ }
+
+ expect(response).not_to redirect_to(group_milestone_path(group, milestone.iid))
+ expect(response).to render_template(:edit)
+ end
end
describe "#destroy" do
diff --git a/spec/controllers/projects/milestones_controller_spec.rb b/spec/controllers/projects/milestones_controller_spec.rb
index 28da7eff8fc..e2b73e55145 100644
--- a/spec/controllers/projects/milestones_controller_spec.rb
+++ b/spec/controllers/projects/milestones_controller_spec.rb
@@ -156,6 +156,27 @@ RSpec.describe Projects::MilestonesController do
end
end
+ describe "#update" do
+ let(:milestone_params) do
+ { title: "title changed" }
+ end
+
+ it "handles ActiveRecord::StaleObjectError" do
+ # Purposely reduce the lock_version to trigger an ActiveRecord::StaleObjectError
+ milestone_params[:lock_version] = milestone.lock_version - 1
+
+ put :update, params: {
+ id: milestone.iid,
+ milestone: milestone_params,
+ namespace_id: project.namespace.id,
+ project_id: project.id
+ }
+
+ expect(response).not_to redirect_to(project_milestone_path(project, milestone.iid))
+ expect(response).to render_template(:edit)
+ end
+ end
+
describe "#destroy" do
it "removes milestone" do
expect(issue.milestone_id).to eq(milestone.id)
diff --git a/spec/factories/container_registry/data_repair_detail.rb b/spec/factories/container_registry/data_repair_detail.rb
new file mode 100644
index 00000000000..79467c464db
--- /dev/null
+++ b/spec/factories/container_registry/data_repair_detail.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :container_registry_data_repair_detail, class: 'ContainerRegistry::DataRepairDetail' do
+ project
+ updated_at { 1.hour.ago }
+
+ trait :ongoing do
+ status { :ongoing }
+ end
+
+ trait :completed do
+ status { :completed }
+ end
+
+ trait :failed do
+ status { :failed }
+ end
+ end
+end
diff --git a/spec/features/groups/milestones/milestone_editing_spec.rb b/spec/features/groups/milestones/milestone_editing_spec.rb
new file mode 100644
index 00000000000..b3c7cfe88af
--- /dev/null
+++ b/spec/features/groups/milestones/milestone_editing_spec.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe "Milestone editing", feature_category: :team_planning do
+ let_it_be(:group) { create(:group, owner: user) }
+ let_it_be(:user) { create(:group_member, :maintainer, user: create(:user), group: group).user }
+
+ let(:milestone) { create(:milestone, group: group, title: "12345676543") }
+
+ before do
+ sign_in(user)
+
+ visit(edit_group_milestone_path(group, milestone))
+ end
+
+ it_behaves_like 'milestone handling version conflicts'
+end
diff --git a/spec/features/issues/user_edits_issue_spec.rb b/spec/features/issues/user_edits_issue_spec.rb
index c1cf8fada26..bc20660d2a0 100644
--- a/spec/features/issues/user_edits_issue_spec.rb
+++ b/spec/features/issues/user_edits_issue_spec.rb
@@ -54,7 +54,7 @@ RSpec.describe "Issues > User edits issue", :js, feature_category: :team_plannin
first('.js-user-search').click
click_link 'Unassigned'
- click_button 'Save changes'
+ click_button _('Save changes')
page.within('.assignee') do
expect(page).to have_content 'None - assign yourself'
@@ -79,7 +79,7 @@ RSpec.describe "Issues > User edits issue", :js, feature_category: :team_plannin
expect(find('#issuable-due-date').value).to eq date.to_s
- click_button 'Save changes'
+ click_button _('Save changes')
page.within '.issuable-sidebar' do
expect(page).to have_content date.to_s(:medium)
@@ -92,9 +92,15 @@ RSpec.describe "Issues > User edits issue", :js, feature_category: :team_plannin
fill_in 'issue_title', with: 'bug 345'
fill_in 'issue_description', with: 'bug description'
- click_button 'Save changes'
+ click_button _('Save changes')
- expect(page).to have_content 'Someone edited the issue the same time you did'
+ expect(page).to have_content(
+ format(
+ _("Someone edited this %{model_name} at the same time you did. Please check out the %{link_to_model} and make sure your changes will not unintentionally remove theirs."), # rubocop:disable Layout/LineLength
+ model_name: _('issue'),
+ link_to_model: _('issue')
+ )
+ )
end
end
end
diff --git a/spec/features/merge_request/user_edits_mr_spec.rb b/spec/features/merge_request/user_edits_mr_spec.rb
index 114fa5b6ecb..76588832ee1 100644
--- a/spec/features/merge_request/user_edits_mr_spec.rb
+++ b/spec/features/merge_request/user_edits_mr_spec.rb
@@ -90,9 +90,15 @@ RSpec.describe 'Merge request > User edits MR', feature_category: :code_review_w
fill_in 'merge_request_title', with: 'bug 345'
fill_in 'merge_request_description', with: 'bug description'
- click_button 'Save changes'
-
- expect(page).to have_content 'Someone edited the merge request the same time you did'
+ click_button _('Save changes')
+
+ expect(page).to have_content(
+ format(
+ _("Someone edited this %{model_name} at the same time you did. Please check out the %{link_to_model} and make sure your changes will not unintentionally remove theirs."), # rubocop:disable Layout/LineLength
+ model_name: _('merge request'),
+ link_to_model: _('merge request')
+ )
+ )
end
it 'preserves description textarea height', :js do
diff --git a/spec/features/projects/blobs/blob_show_spec.rb b/spec/features/projects/blobs/blob_show_spec.rb
index 74e5dc9f8c3..cd1dde55e30 100644
--- a/spec/features/projects/blobs/blob_show_spec.rb
+++ b/spec/features/projects/blobs/blob_show_spec.rb
@@ -580,7 +580,11 @@ RSpec.describe 'File blob', :js, feature_category: :projects do
end
describe '.gitlab/dashboards/custom-dashboard.yml' do
+ let(:remove_monitor_metrics) { false }
+
before do
+ stub_feature_flags(remove_monitor_metrics: remove_monitor_metrics)
+
project.add_maintainer(project.creator)
Files::CreateService.new(
@@ -608,6 +612,15 @@ RSpec.describe 'File blob', :js, feature_category: :projects do
expect(page).to have_link('Learn more')
end
end
+
+ context 'when metrics dashboard feature is unavailable' do
+ let(:remove_monitor_metrics) { true }
+
+ it 'displays the blob without an auxiliary viewer' do
+ expect(page).to have_content('Environment metrics')
+ expect(page).not_to have_content('Metrics Dashboard YAML definition', wait: 0)
+ end
+ end
end
context 'invalid dashboard file' do
diff --git a/spec/features/projects/integrations/user_activates_mattermost_slash_command_spec.rb b/spec/features/projects/integrations/user_activates_mattermost_slash_command_spec.rb
index c2370f38faa..aea76944c7f 100644
--- a/spec/features/projects/integrations/user_activates_mattermost_slash_command_spec.rb
+++ b/spec/features/projects/integrations/user_activates_mattermost_slash_command_spec.rb
@@ -99,7 +99,7 @@ RSpec.describe 'Set up Mattermost slash commands', :js, feature_category: :integ
click_link 'Add to Mattermost'
- expect(find('input[type="submit"]')['disabled']).not_to eq("true")
+ expect(find('button[type="submit"]')['disabled']).not_to eq("true")
end
it 'disables the submit button if the required fields are not provided', :js do
@@ -109,7 +109,7 @@ RSpec.describe 'Set up Mattermost slash commands', :js, feature_category: :integ
fill_in('mattermost_trigger', with: '')
- expect(find('input[type="submit"]')['disabled']).to eq("true")
+ expect(find('button[type="submit"]')['disabled']).to eq("true")
end
def stub_teams(count: 0)
diff --git a/spec/features/projects/milestones/milestone_editing_spec.rb b/spec/features/projects/milestones/milestone_editing_spec.rb
new file mode 100644
index 00000000000..8a03683eb35
--- /dev/null
+++ b/spec/features/projects/milestones/milestone_editing_spec.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe "Milestone editing", :js, feature_category: :team_planning do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, name: 'test', namespace: user.namespace) }
+
+ let(:milestone) { create(:milestone, project: project, start_date: Date.today, due_date: 5.days.from_now) }
+
+ before do
+ sign_in(user)
+
+ visit(edit_project_milestone_path(project, milestone))
+ end
+
+ it_behaves_like 'milestone handling version conflicts'
+end
diff --git a/spec/finders/template_finder_spec.rb b/spec/finders/template_finder_spec.rb
index 21fea7863ff..c466f533a61 100644
--- a/spec/finders/template_finder_spec.rb
+++ b/spec/finders/template_finder_spec.rb
@@ -103,6 +103,10 @@ RSpec.describe TemplateFinder do
describe '#build' do
let(:project) { build_stubbed(:project) }
+ before do
+ stub_feature_flags(remove_monitor_metrics: false)
+ end
+
where(:type, :expected_class) do
:dockerfiles | described_class
:gitignores | described_class
@@ -119,6 +123,16 @@ RSpec.describe TemplateFinder do
it { is_expected.to be_a(expected_class) }
it { expect(finder.project).to eq(project) }
end
+
+ context 'when metrics dashboard is unavailable' do
+ before do
+ stub_feature_flags(remove_monitor_metrics: true)
+ end
+
+ subject(:finder) { described_class.build(:metrics_dashboard_ymls, project) }
+
+ it { is_expected.to be_nil }
+ end
end
describe '#execute' do
diff --git a/spec/frontend/ci/pipeline_editor/components/job_assistant_drawer/accordion_items/image_item_spec.js b/spec/frontend/ci/pipeline_editor/components/job_assistant_drawer/accordion_items/image_item_spec.js
index c7c40c3a4b9..f99d7277612 100644
--- a/spec/frontend/ci/pipeline_editor/components/job_assistant_drawer/accordion_items/image_item_spec.js
+++ b/spec/frontend/ci/pipeline_editor/components/job_assistant_drawer/accordion_items/image_item_spec.js
@@ -8,8 +8,8 @@ describe('Image item', () => {
const findImageNameInput = () => wrapper.findByTestId('image-name-input');
const findImageEntrypointInput = () => wrapper.findByTestId('image-entrypoint-input');
- const dummyImageName = 'dummyImageName';
- const dummyImageEntrypoint = 'dummyImageEntrypoint';
+ const dummyImageName = 'a';
+ const dummyImageEntrypoint = ['b', 'c'];
const createComponent = ({ job = JSON.parse(JSON.stringify(JOB_TEMPLATE)) } = {}) => {
wrapper = shallowMountExtended(ImageItem, {
@@ -31,9 +31,9 @@ describe('Image item', () => {
expect(wrapper.emitted('update-job')).toHaveLength(1);
expect(wrapper.emitted('update-job')[0]).toEqual(['image.name', dummyImageName]);
- findImageEntrypointInput().vm.$emit('input', dummyImageEntrypoint);
+ findImageEntrypointInput().vm.$emit('input', dummyImageEntrypoint.join('\n'));
expect(wrapper.emitted('update-job')).toHaveLength(2);
- expect(wrapper.emitted('update-job')[1]).toEqual(['image.entrypoint', [dummyImageEntrypoint]]);
+ expect(wrapper.emitted('update-job')[1]).toEqual(['image.entrypoint', dummyImageEntrypoint]);
});
});
diff --git a/spec/frontend/ci/pipeline_editor/components/job_assistant_drawer/accordion_items/services_item_spec.js b/spec/frontend/ci/pipeline_editor/components/job_assistant_drawer/accordion_items/services_item_spec.js
index 07b3526f5fa..284d639c77f 100644
--- a/spec/frontend/ci/pipeline_editor/components/job_assistant_drawer/accordion_items/services_item_spec.js
+++ b/spec/frontend/ci/pipeline_editor/components/job_assistant_drawer/accordion_items/services_item_spec.js
@@ -34,7 +34,7 @@ describe('Services item', () => {
expect(wrapper.emitted('update-job')).toHaveLength(1);
expect(wrapper.emitted('update-job')[0]).toEqual(['services[0].name', dummyServiceName]);
- findServiceEntrypointInputByIndex(0).vm.$emit('input', dummyServiceEntrypoint.join(','));
+ findServiceEntrypointInputByIndex(0).vm.$emit('input', dummyServiceEntrypoint.join('\n'));
expect(wrapper.emitted('update-job')).toHaveLength(2);
expect(wrapper.emitted('update-job')[1]).toEqual([
diff --git a/spec/graphql/resolvers/metrics/dashboards/annotation_resolver_spec.rb b/spec/graphql/resolvers/metrics/dashboards/annotation_resolver_spec.rb
index a83cef40bdf..2ca194d519c 100644
--- a/spec/graphql/resolvers/metrics/dashboards/annotation_resolver_spec.rb
+++ b/spec/graphql/resolvers/metrics/dashboards/annotation_resolver_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Resolvers::Metrics::Dashboards::AnnotationResolver do
+RSpec.describe Resolvers::Metrics::Dashboards::AnnotationResolver, feature_category: :metrics do
include GraphqlHelpers
describe '#resolve' do
@@ -25,6 +25,10 @@ RSpec.describe Resolvers::Metrics::Dashboards::AnnotationResolver do
environment.project.add_developer(current_user)
end
+ before do
+ stub_feature_flags(remove_monitor_metrics: false)
+ end
+
context 'with annotation records' do
let_it_be(:annotation_1) { create(:metrics_dashboard_annotation, environment: environment, starting_at: 9.minutes.ago, dashboard_path: path) }
@@ -55,6 +59,16 @@ RSpec.describe Resolvers::Metrics::Dashboards::AnnotationResolver do
expect(resolve_annotations).to be_empty
end
end
+
+ context 'when metrics dashboard feature is unavailable' do
+ before do
+ stub_feature_flags(remove_monitor_metrics: true)
+ end
+
+ it 'returns nothing' do
+ expect(resolve_annotations).to be_nil
+ end
+ end
end
end
end
diff --git a/spec/graphql/types/permission_types/issue_spec.rb b/spec/graphql/types/permission_types/issue_spec.rb
index 58c5808cbcc..8f43a4a44a0 100644
--- a/spec/graphql/types/permission_types/issue_spec.rb
+++ b/spec/graphql/types/permission_types/issue_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe Types::PermissionTypes::Issue do
expected_permissions = [
:read_issue, :admin_issue, :update_issue, :reopen_issue,
:read_design, :create_design, :destroy_design,
- :create_note
+ :create_note, :update_design
]
expected_permissions.each do |permission|
diff --git a/spec/graphql/types/project_statistics_redirect_type_spec.rb b/spec/graphql/types/project_statistics_redirect_type_spec.rb
new file mode 100644
index 00000000000..3600a5b932f
--- /dev/null
+++ b/spec/graphql/types/project_statistics_redirect_type_spec.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['ProjectStatisticsRedirect'], feature_category: :consumables_cost_management do
+ it 'has all the required fields' do
+ expect(described_class).to have_graphql_fields(:repository, :build_artifacts, :packages,
+ :wiki, :snippets, :container_registry)
+ end
+end
diff --git a/spec/graphql/types/project_type_spec.rb b/spec/graphql/types/project_type_spec.rb
index 0f980241db3..bcfdb05ca90 100644
--- a/spec/graphql/types/project_type_spec.rb
+++ b/spec/graphql/types/project_type_spec.rb
@@ -24,7 +24,7 @@ RSpec.describe GitlabSchema.types['Project'] do
snippets_enabled jobs_enabled public_jobs open_issues_count import_status
only_allow_merge_if_pipeline_succeeds request_access_enabled
only_allow_merge_if_all_discussions_are_resolved printing_merge_request_link_enabled
- namespace group statistics repository merge_requests merge_request issues
+ namespace group statistics statistics_details_paths repository merge_requests merge_request issues
issue milestones pipelines removeSourceBranchAfterMerge pipeline_counts sentryDetailedError snippets
grafanaIntegration autocloseReferencedIssues suggestion_commit_message environments
environment boards jira_import_status jira_imports services releases release
diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb
index f7cbe8c816b..3eb1090c9dc 100644
--- a/spec/helpers/projects_helper_spec.rb
+++ b/spec/helpers/projects_helper_spec.rb
@@ -777,6 +777,34 @@ RSpec.describe ProjectsHelper, feature_category: :source_code_management do
end
end
+ describe '#show_mobile_devops_project_promo?' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:hide_cookie, :feature_flag_enabled, :mobile_target_platform, :result) do
+ false | true | true | true
+ false | false | true | false
+ false | false | false | false
+ false | true | false | false
+ true | false | false | false
+ true | true | false | false
+ true | true | true | false
+ true | false | true | false
+ end
+
+ with_them do
+ before do
+ allow(Gitlab).to receive(:com?) { gitlab_com }
+ Feature.enable(:mobile_devops_projects_promo, feature_flag_enabled)
+ project.project_setting.target_platforms << 'ios' if mobile_target_platform
+ helper.request.cookies["hide_mobile_devops_promo_#{project.id}"] = true if hide_cookie
+ end
+
+ it 'resolves if the user can import members' do
+ expect(helper.show_mobile_devops_project_promo?(project)).to eq result
+ end
+ end
+ end
+
describe '#can_admin_project_member?' do
context 'when user is project owner' do
before do
diff --git a/spec/lib/api/entities/package_spec.rb b/spec/lib/api/entities/package_spec.rb
index 53d9a0b4557..9288f6fe8eb 100644
--- a/spec/lib/api/entities/package_spec.rb
+++ b/spec/lib/api/entities/package_spec.rb
@@ -40,13 +40,4 @@ RSpec.describe API::Entities::Package do
expect(subject[:_links]).not_to have_key(:web_path)
end
end
-
- context 'with build info' do
- let_it_be(:project) { create(:project) }
- let_it_be(:package) { create(:npm_package, :with_build, project: project) }
-
- it 'returns an empty array for pipelines' do
- expect(subject[:pipelines]).to eq([])
- end
- end
end
diff --git a/spec/lib/container_registry/gitlab_api_client_spec.rb b/spec/lib/container_registry/gitlab_api_client_spec.rb
index ac15048e4b5..c70dd265073 100644
--- a/spec/lib/container_registry/gitlab_api_client_spec.rb
+++ b/spec/lib/container_registry/gitlab_api_client_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe ContainerRegistry::GitlabApiClient do
+RSpec.describe ContainerRegistry::GitlabApiClient, feature_category: :container_registry do
using RSpec::Parameterized::TableSyntax
include_context 'container registry client'
@@ -615,6 +615,159 @@ RSpec.describe ContainerRegistry::GitlabApiClient do
end
end
+ describe '#each_sub_repositories_with_tag_page' do
+ let(:page_size) { 100 }
+ let(:project_path) { 'repo/project' }
+
+ shared_examples 'iterating through a page' do |expected_tags: true|
+ it 'iterates through one page' do
+ expect_next_instance_of(described_class) do |client|
+ expect(client).to receive(:sub_repositories_with_tag).with(project_path, page_size: page_size, last: nil).and_return(client_response)
+ end
+
+ expect { |b| described_class.each_sub_repositories_with_tag_page(path: project_path, page_size: page_size, &b) }
+ .to yield_with_args(expected_tags ? client_response_repositories : [])
+ end
+ end
+
+ context 'when no block is given' do
+ it 'raises an Argument error' do
+ expect do
+ described_class.each_sub_repositories_with_tag_page(path: project_path, page_size: page_size)
+ end.to raise_error(ArgumentError, 'block not given')
+ end
+ end
+
+ context 'when a block is given' do
+ before do
+ expect(Auth::ContainerRegistryAuthenticationService).to receive(:pull_nested_repositories_access_token).with(project_path).and_return(token)
+ stub_container_registry_config(enabled: true, api_url: registry_api_url, key: 'spec/fixtures/x509_certificate_pk.key')
+ end
+
+ context 'with an empty page' do
+ let(:client_response) { { pagination: {}, response_body: [] } }
+
+ it_behaves_like 'iterating through a page', expected_tags: false
+ end
+
+ context 'with one page' do
+ let(:client_response) { { pagination: {}, response_body: client_response_repositories } }
+ let(:client_response_repositories) do
+ [
+ {
+ "name": "docker-alpine",
+ "path": "gitlab-org/build/cng/docker-alpine",
+ "created_at": "2022-06-07T12:11:13.633+00:00",
+ "updated_at": "2022-06-07T14:37:49.251+00:00"
+ },
+ {
+ "name": "git-base",
+ "path": "gitlab-org/build/cng/git-base",
+ "created_at": "2022-06-07T12:11:13.633+00:00",
+ "updated_at": "2022-06-07T14:37:49.251+00:00"
+ }
+ ]
+ end
+
+ it_behaves_like 'iterating through a page'
+ end
+
+ context 'with two pages' do
+ let(:client_response1) { { pagination: { next: { uri: URI('http://localhost/next?last=latest') } }, response_body: client_response_repositories1 } }
+ let(:client_response_repositories1) do
+ [
+ {
+ "name": "docker-alpine",
+ "path": "gitlab-org/build/cng/docker-alpine",
+ "created_at": "2022-06-07T12:11:13.633+00:00",
+ "updated_at": "2022-06-07T14:37:49.251+00:00"
+ },
+ {
+ "name": "git-base",
+ "path": "gitlab-org/build/cng/git-base",
+ "created_at": "2022-06-07T12:11:13.633+00:00",
+ "updated_at": "2022-06-07T14:37:49.251+00:00"
+ }
+ ]
+ end
+
+ let(:client_response2) { { pagination: {}, response_body: client_response_repositories2 } }
+ let(:client_response_repositories2) do
+ [
+ {
+ "name": "docker-alpine1",
+ "path": "gitlab-org/build/cng/docker-alpine",
+ "created_at": "2022-06-07T12:11:13.633+00:00",
+ "updated_at": "2022-06-07T14:37:49.251+00:00"
+ },
+ {
+ "name": "git-base1",
+ "path": "gitlab-org/build/cng/git-base",
+ "created_at": "2022-06-07T12:11:13.633+00:00",
+ "updated_at": "2022-06-07T14:37:49.251+00:00"
+ }
+ ]
+ end
+
+ it 'iterates through two pages' do
+ expect_next_instance_of(described_class) do |client|
+ expect(client).to receive(:sub_repositories_with_tag).with(project_path, page_size: page_size, last: nil).and_return(client_response1)
+ expect(client).to receive(:sub_repositories_with_tag).with(project_path, page_size: page_size, last: 'latest').and_return(client_response2)
+ end
+
+ expect { |b| described_class.each_sub_repositories_with_tag_page(path: project_path, page_size: page_size, &b) }
+ .to yield_successive_args(client_response_repositories1, client_response_repositories2)
+ end
+ end
+
+ context 'when max pages is reached' do
+ let(:client_response) { { pagination: {}, response_body: [] } }
+
+ before do
+ stub_const('ContainerRegistry::GitlabApiClient::MAX_REPOSITORIES_PAGE_SIZE', 0)
+ expect_next_instance_of(described_class) do |client|
+ expect(client).to receive(:sub_repositories_with_tag).with(project_path, page_size: page_size, last: nil).and_return(client_response)
+ end
+ end
+
+ it 'raises an error' do
+ expect { described_class.each_sub_repositories_with_tag_page(path: project_path, page_size: page_size) {} } # rubocop:disable Lint/EmptyBlock
+ .to raise_error(StandardError, 'too many pages requested')
+ end
+ end
+
+ context 'without a page size set' do
+ let(:client_response) { { pagination: {}, response_body: [] } }
+
+ it 'uses a default size' do
+ expect_next_instance_of(described_class) do |client|
+ expect(client).to receive(:sub_repositories_with_tag).with(project_path, page_size: page_size, last: nil).and_return(client_response)
+ end
+
+ expect { |b| described_class.each_sub_repositories_with_tag_page(path: project_path, &b) }.to yield_with_args([])
+ end
+ end
+
+ context 'with an empty client response' do
+ let(:client_response) { {} }
+
+ it 'breaks the loop' do
+ expect_next_instance_of(described_class) do |client|
+ expect(client).to receive(:sub_repositories_with_tag).with(project_path, page_size: page_size, last: nil).and_return(client_response)
+ end
+
+ expect { |b| described_class.each_sub_repositories_with_tag_page(path: project_path, page_size: page_size, &b) }.not_to yield_control
+ end
+ end
+
+ context 'with a nil page' do
+ let(:client_response) { { pagination: {}, response_body: nil } }
+
+ it_behaves_like 'iterating through a page', expected_tags: false
+ end
+ end
+ end
+
def stub_pre_import(path, status_code, pre:)
import_type = pre ? 'pre' : 'final'
stub_request(:put, "#{registry_api_url}/gitlab/v1/import/#{path}/?import_type=#{import_type}")
diff --git a/spec/lib/gitlab/background_migration/backfill_cluster_agents_has_vulnerabilities_spec.rb b/spec/lib/gitlab/background_migration/backfill_cluster_agents_has_vulnerabilities_spec.rb
index 3aab0cdf54b..edb6ff59340 100644
--- a/spec/lib/gitlab/background_migration/backfill_cluster_agents_has_vulnerabilities_spec.rb
+++ b/spec/lib/gitlab/background_migration/backfill_cluster_agents_has_vulnerabilities_spec.rb
@@ -4,10 +4,12 @@ require 'spec_helper'
RSpec.describe Gitlab::BackgroundMigration::BackfillClusterAgentsHasVulnerabilities, :migration do # rubocop:disable Layout/LineLength
let(:migration) do
- described_class.new(start_id: 1, end_id: 10,
- batch_table: table_name, batch_column: batch_column,
- sub_batch_size: sub_batch_size, pause_ms: pause_ms,
- connection: ApplicationRecord.connection)
+ described_class.new(
+ start_id: 1, end_id: 10,
+ batch_table: table_name, batch_column: batch_column,
+ sub_batch_size: sub_batch_size, pause_ms: pause_ms,
+ connection: ApplicationRecord.connection
+ )
end
let(:users_table) { table(:users) }
diff --git a/spec/lib/gitlab/background_migration/backfill_environment_tiers_spec.rb b/spec/lib/gitlab/background_migration/backfill_environment_tiers_spec.rb
index 788ed40b61e..9026c327e3c 100644
--- a/spec/lib/gitlab/background_migration/backfill_environment_tiers_spec.rb
+++ b/spec/lib/gitlab/background_migration/backfill_environment_tiers_spec.rb
@@ -8,10 +8,12 @@ RSpec.describe Gitlab::BackgroundMigration::BackfillEnvironmentTiers,
let!(:project) { table(:projects).create!(namespace_id: namespace.id, project_namespace_id: namespace.id) }
let(:migration) do
- described_class.new(start_id: 1, end_id: 1000,
- batch_table: :environments, batch_column: :id,
- sub_batch_size: 10, pause_ms: 0,
- connection: ApplicationRecord.connection)
+ described_class.new(
+ start_id: 1, end_id: 1000,
+ batch_table: :environments, batch_column: :id,
+ sub_batch_size: 10, pause_ms: 0,
+ connection: ApplicationRecord.connection
+ )
end
describe '#perform' do
diff --git a/spec/lib/gitlab/background_migration/backfill_group_features_spec.rb b/spec/lib/gitlab/background_migration/backfill_group_features_spec.rb
index e0be5a785b8..023d4b04e63 100644
--- a/spec/lib/gitlab/background_migration/backfill_group_features_spec.rb
+++ b/spec/lib/gitlab/background_migration/backfill_group_features_spec.rb
@@ -7,14 +7,16 @@ RSpec.describe Gitlab::BackgroundMigration::BackfillGroupFeatures, :migration, s
let(:namespaces) { table(:namespaces) }
subject do
- described_class.new(start_id: 1,
- end_id: 4,
- batch_table: :namespaces,
- batch_column: :id,
- sub_batch_size: 10,
- pause_ms: 0,
- job_arguments: [4],
- connection: ActiveRecord::Base.connection)
+ described_class.new(
+ start_id: 1,
+ end_id: 4,
+ batch_table: :namespaces,
+ batch_column: :id,
+ sub_batch_size: 10,
+ pause_ms: 0,
+ job_arguments: [4],
+ connection: ActiveRecord::Base.connection
+ )
end
describe '#perform' do
diff --git a/spec/lib/gitlab/background_migration/backfill_imported_issue_search_data_spec.rb b/spec/lib/gitlab/background_migration/backfill_imported_issue_search_data_spec.rb
index 479afb56210..b3f04055e0a 100644
--- a/spec/lib/gitlab/background_migration/backfill_imported_issue_search_data_spec.rb
+++ b/spec/lib/gitlab/background_migration/backfill_imported_issue_search_data_spec.rb
@@ -30,13 +30,15 @@ RSpec.describe Gitlab::BackgroundMigration::BackfillImportedIssueSearchData,
end
let(:migration) do
- described_class.new(start_id: issue.id,
- end_id: issue.id + 30,
- batch_table: :issues,
- batch_column: :id,
- sub_batch_size: 2,
- pause_ms: 0,
- connection: ApplicationRecord.connection)
+ described_class.new(
+ start_id: issue.id,
+ end_id: issue.id + 30,
+ batch_table: :issues,
+ batch_column: :id,
+ sub_batch_size: 2,
+ pause_ms: 0,
+ connection: ApplicationRecord.connection
+ )
end
let(:perform_migration) { migration.perform }
diff --git a/spec/lib/gitlab/background_migration/backfill_namespace_details_spec.rb b/spec/lib/gitlab/background_migration/backfill_namespace_details_spec.rb
index b6282de0da6..39ad60fb13b 100644
--- a/spec/lib/gitlab/background_migration/backfill_namespace_details_spec.rb
+++ b/spec/lib/gitlab/background_migration/backfill_namespace_details_spec.rb
@@ -7,27 +7,36 @@ RSpec.describe Gitlab::BackgroundMigration::BackfillNamespaceDetails, :migration
let(:namespace_details) { table(:namespace_details) }
subject(:perform_migration) do
- described_class.new(start_id: namespaces.minimum(:id),
- end_id: namespaces.maximum(:id),
- batch_table: :namespaces,
- batch_column: :id,
- sub_batch_size: 2,
- pause_ms: 0,
- connection: ActiveRecord::Base.connection)
- .perform
+ described_class.new(
+ start_id: namespaces.minimum(:id),
+ end_id: namespaces.maximum(:id),
+ batch_table: :namespaces,
+ batch_column: :id,
+ sub_batch_size: 2,
+ pause_ms: 0,
+ connection: ActiveRecord::Base.connection
+ ).perform
end
describe '#perform' do
it 'creates details for all namespaces in range' do
- namespace1 = namespaces.create!(id: 5, name: 'test1', path: 'test1', description: "Some description1",
- description_html: "Some description html1", cached_markdown_version: 4)
- namespaces.create!(id: 6, name: 'test2', path: 'test2', type: 'Project',
- description: "Some description2", description_html: "Some description html2",
- cached_markdown_version: 4)
- namespace3 = namespaces.create!(id: 7, name: 'test3', path: 'test3', description: "Some description3",
- description_html: "Some description html3", cached_markdown_version: 4)
- namespace4 = namespaces.create!(id: 8, name: 'test4', path: 'test4', description: "Some description3",
- description_html: "Some description html4", cached_markdown_version: 4)
+ namespace1 = namespaces.create!(
+ id: 5, name: 'test1', path: 'test1', description: "Some description1",
+ description_html: "Some description html1", cached_markdown_version: 4
+ )
+ namespaces.create!(
+ id: 6, name: 'test2', path: 'test2', type: 'Project',
+ description: "Some description2", description_html: "Some description html2",
+ cached_markdown_version: 4
+ )
+ namespace3 = namespaces.create!(
+ id: 7, name: 'test3', path: 'test3', description: "Some description3",
+ description_html: "Some description html3", cached_markdown_version: 4
+ )
+ namespace4 = namespaces.create!(
+ id: 8, name: 'test4', path: 'test4', description: "Some description3",
+ description_html: "Some description html4", cached_markdown_version: 4
+ )
namespace_details.delete_all
expect(namespace_details.pluck(:namespace_id)).to eql []
diff --git a/spec/lib/gitlab/background_migration/backfill_namespace_id_for_namespace_route_spec.rb b/spec/lib/gitlab/background_migration/backfill_namespace_id_for_namespace_route_spec.rb
index b821efcadb0..3a8a327550b 100644
--- a/spec/lib/gitlab/background_migration/backfill_namespace_id_for_namespace_route_spec.rb
+++ b/spec/lib/gitlab/background_migration/backfill_namespace_id_for_namespace_route_spec.rb
@@ -22,18 +22,29 @@ RSpec.describe Gitlab::BackgroundMigration::BackfillNamespaceIdForNamespaceRoute
subject(:perform_migration) { migration.perform(1, 10, table_name, batch_column, sub_batch_size, pause_ms) }
before do
- routes_table.create!(id: 1, name: 'test1', path: 'test1', source_id: namespace1.id,
- source_type: namespace1.class.sti_name)
- routes_table.create!(id: 2, name: 'test2', path: 'test2', source_id: namespace2.id,
- source_type: namespace2.class.sti_name)
- routes_table.create!(id: 5, name: 'test3', path: 'test3', source_id: project1.id,
- source_type: project1.class.sti_name) # should be ignored - project route
- routes_table.create!(id: 6, name: 'test4', path: 'test4', source_id: non_existing_record_id,
- source_type: namespace3.class.sti_name) # should be ignored - invalid source_id
- routes_table.create!(id: 10, name: 'test5', path: 'test5', source_id: namespace3.id,
- source_type: namespace3.class.sti_name)
- routes_table.create!(id: 11, name: 'test6', path: 'test6', source_id: namespace4.id,
- source_type: namespace4.class.sti_name) # should be ignored - outside the scope
+ routes_table.create!(
+ id: 1, name: 'test1', path: 'test1', source_id: namespace1.id, source_type: namespace1.class.sti_name
+ )
+
+ routes_table.create!(
+ id: 2, name: 'test2', path: 'test2', source_id: namespace2.id, source_type: namespace2.class.sti_name
+ )
+
+ routes_table.create!(
+ id: 5, name: 'test3', path: 'test3', source_id: project1.id, source_type: project1.class.sti_name
+ ) # should be ignored - project route
+
+ routes_table.create!(
+ id: 6, name: 'test4', path: 'test4', source_id: non_existing_record_id, source_type: namespace3.class.sti_name
+ ) # should be ignored - invalid source_id
+
+ routes_table.create!(
+ id: 10, name: 'test5', path: 'test5', source_id: namespace3.id, source_type: namespace3.class.sti_name
+ )
+
+ routes_table.create!(
+ id: 11, name: 'test6', path: 'test6', source_id: namespace4.id, source_type: namespace4.class.sti_name
+ ) # should be ignored - outside the scope
end
it 'backfills `type` for the selected records', :aggregate_failures do
diff --git a/spec/lib/gitlab/background_migration/backfill_namespace_id_of_vulnerability_reads_spec.rb b/spec/lib/gitlab/background_migration/backfill_namespace_id_of_vulnerability_reads_spec.rb
index 564aa3b8c01..6a55c6951d5 100644
--- a/spec/lib/gitlab/background_migration/backfill_namespace_id_of_vulnerability_reads_spec.rb
+++ b/spec/lib/gitlab/background_migration/backfill_namespace_id_of_vulnerability_reads_spec.rb
@@ -38,14 +38,15 @@ RSpec.describe Gitlab::BackgroundMigration::BackfillNamespaceIdOfVulnerabilityRe
end
subject(:perform_migration) do
- described_class.new(start_id: vulnerability_read.vulnerability_id,
- end_id: vulnerability_read.vulnerability_id,
- batch_table: :vulnerability_reads,
- batch_column: :vulnerability_id,
- sub_batch_size: 1,
- pause_ms: 0,
- connection: ActiveRecord::Base.connection)
- .perform
+ described_class.new(
+ start_id: vulnerability_read.vulnerability_id,
+ end_id: vulnerability_read.vulnerability_id,
+ batch_table: :vulnerability_reads,
+ batch_column: :vulnerability_id,
+ sub_batch_size: 1,
+ pause_ms: 0,
+ connection: ActiveRecord::Base.connection
+ ).perform
end
it 'sets the namespace_id of existing record' do
diff --git a/spec/lib/gitlab/background_migration/backfill_project_feature_package_registry_access_level_spec.rb b/spec/lib/gitlab/background_migration/backfill_project_feature_package_registry_access_level_spec.rb
index fd6c055b9f6..47ff2883fb2 100644
--- a/spec/lib/gitlab/background_migration/backfill_project_feature_package_registry_access_level_spec.rb
+++ b/spec/lib/gitlab/background_migration/backfill_project_feature_package_registry_access_level_spec.rb
@@ -101,14 +101,15 @@ RSpec.describe Gitlab::BackgroundMigration::BackfillProjectFeaturePackageRegistr
end
subject(:perform_migration) do
- described_class.new(start_id: project1.id,
- end_id: project5.id,
- batch_table: :projects,
- batch_column: :id,
- sub_batch_size: 2,
- pause_ms: 0,
- connection: ActiveRecord::Base.connection)
- .perform
+ described_class.new(
+ start_id: project1.id,
+ end_id: project5.id,
+ batch_table: :projects,
+ batch_column: :id,
+ sub_batch_size: 2,
+ pause_ms: 0,
+ connection: ActiveRecord::Base.connection
+ ).perform
end
it 'backfills project_features.package_registry_access_level', :aggregate_failures do
diff --git a/spec/lib/gitlab/background_migration/backfill_project_member_namespace_id_spec.rb b/spec/lib/gitlab/background_migration/backfill_project_member_namespace_id_spec.rb
index ca7ca41a33e..96f49624d22 100644
--- a/spec/lib/gitlab/background_migration/backfill_project_member_namespace_id_spec.rb
+++ b/spec/lib/gitlab/background_migration/backfill_project_member_namespace_id_spec.rb
@@ -4,10 +4,12 @@ require 'spec_helper'
RSpec.describe Gitlab::BackgroundMigration::BackfillProjectMemberNamespaceId, :migration, schema: 20220516054011 do
let(:migration) do
- described_class.new(start_id: 1, end_id: 10,
- batch_table: table_name, batch_column: batch_column,
- sub_batch_size: sub_batch_size, pause_ms: pause_ms,
- connection: ApplicationRecord.connection)
+ described_class.new(
+ start_id: 1, end_id: 10,
+ batch_table: table_name, batch_column: batch_column,
+ sub_batch_size: sub_batch_size, pause_ms: pause_ms,
+ connection: ApplicationRecord.connection
+ )
end
let(:members_table) { table(:members) }
@@ -35,37 +37,55 @@ RSpec.describe Gitlab::BackgroundMigration::BackfillProjectMemberNamespaceId, :m
projects_table.create!(id: 102, name: 'project3', path: 'project3', namespace_id: 202, project_namespace_id: 302)
# project1, no member namespace (fill in)
- members_table.create!(id: 1, source_id: 100,
- source_type: 'Project', type: 'ProjectMember',
- member_namespace_id: nil, access_level: 10, notification_level: 3)
+ members_table.create!(
+ id: 1, source_id: 100,
+ source_type: 'Project', type: 'ProjectMember',
+ member_namespace_id: nil, access_level: 10, notification_level: 3
+ )
+
# bogus source id, no member namespace id (do nothing)
- members_table.create!(id: 2, source_id: non_existing_record_id,
- source_type: 'Project', type: 'ProjectMember',
- member_namespace_id: nil, access_level: 10, notification_level: 3)
+ members_table.create!(
+ id: 2, source_id: non_existing_record_id,
+ source_type: 'Project', type: 'ProjectMember',
+ member_namespace_id: nil, access_level: 10, notification_level: 3
+ )
+
# project3, existing member namespace id (do nothing)
- members_table.create!(id: 3, source_id: 102,
- source_type: 'Project', type: 'ProjectMember',
- member_namespace_id: 300, access_level: 10, notification_level: 3)
+ members_table.create!(
+ id: 3, source_id: 102,
+ source_type: 'Project', type: 'ProjectMember',
+ member_namespace_id: 300, access_level: 10, notification_level: 3
+ )
# Group memberships (do not change)
# group1, no member namespace (do nothing)
- members_table.create!(id: 4, source_id: 201,
- source_type: 'Namespace', type: 'GroupMember',
- member_namespace_id: nil, access_level: 10, notification_level: 3)
+ members_table.create!(
+ id: 4, source_id: 201,
+ source_type: 'Namespace', type: 'GroupMember',
+ member_namespace_id: nil, access_level: 10, notification_level: 3
+ )
+
# group2, existing member namespace (do nothing)
- members_table.create!(id: 5, source_id: 202,
- source_type: 'Namespace', type: 'GroupMember',
- member_namespace_id: 201, access_level: 10, notification_level: 3)
+ members_table.create!(
+ id: 5, source_id: 202,
+ source_type: 'Namespace', type: 'GroupMember',
+ member_namespace_id: 201, access_level: 10, notification_level: 3
+ )
# Project Namespace memberships (do not change)
# project namespace, existing member namespace (do nothing)
- members_table.create!(id: 6, source_id: 300,
- source_type: 'Namespace', type: 'ProjectNamespaceMember',
- member_namespace_id: 201, access_level: 10, notification_level: 3)
+ members_table.create!(
+ id: 6, source_id: 300,
+ source_type: 'Namespace', type: 'ProjectNamespaceMember',
+ member_namespace_id: 201, access_level: 10, notification_level: 3
+ )
+
# project namespace, not member namespace (do nothing)
- members_table.create!(id: 7, source_id: 301,
- source_type: 'Namespace', type: 'ProjectNamespaceMember',
- member_namespace_id: 201, access_level: 10, notification_level: 3)
+ members_table.create!(
+ id: 7, source_id: 301,
+ source_type: 'Namespace', type: 'ProjectNamespaceMember',
+ member_namespace_id: 201, access_level: 10, notification_level: 3
+ )
end
it 'backfills `member_namespace_id` for the selected records', :aggregate_failures do
diff --git a/spec/lib/gitlab/background_migration/backfill_project_namespace_details_spec.rb b/spec/lib/gitlab/background_migration/backfill_project_namespace_details_spec.rb
index 01daf16d10c..aac17a426b5 100644
--- a/spec/lib/gitlab/background_migration/backfill_project_namespace_details_spec.rb
+++ b/spec/lib/gitlab/background_migration/backfill_project_namespace_details_spec.rb
@@ -8,32 +8,41 @@ RSpec.describe Gitlab::BackgroundMigration::BackfillProjectNamespaceDetails, :mi
let!(:projects) { table(:projects) }
subject(:perform_migration) do
- described_class.new(start_id: projects.minimum(:id),
- end_id: projects.maximum(:id),
- batch_table: :projects,
- batch_column: :id,
- sub_batch_size: 2,
- pause_ms: 0,
- connection: ActiveRecord::Base.connection)
- .perform
+ described_class.new(
+ start_id: projects.minimum(:id),
+ end_id: projects.maximum(:id),
+ batch_table: :projects,
+ batch_column: :id,
+ sub_batch_size: 2,
+ pause_ms: 0,
+ connection: ActiveRecord::Base.connection
+ ).perform
end
describe '#perform' do
it 'creates details for all project namespaces in range' do
- namespaces.create!(id: 5, name: 'test1', path: 'test1', description: "Some description1",
- description_html: "Some description html1", cached_markdown_version: 4)
+ namespaces.create!(
+ id: 5, name: 'test1', path: 'test1', description: "Some description1",
+ description_html: "Some description html1", cached_markdown_version: 4
+ )
project_namespace1 = namespaces.create!(id: 6, name: 'test2', path: 'test2', type: 'Project')
- namespaces.create!(id: 7, name: 'test3', path: 'test3', description: "Some description3",
- description_html: "Some description html3", cached_markdown_version: 4)
+ namespaces.create!(
+ id: 7, name: 'test3', path: 'test3', description: "Some description3",
+ description_html: "Some description html3", cached_markdown_version: 4
+ )
project_namespace2 = namespaces.create!(id: 8, name: 'test4', path: 'test4', type: 'Project')
- project1 = projects.create!(namespace_id: project_namespace1.id, name: 'gitlab1', path: 'gitlab1',
- project_namespace_id: project_namespace1.id, description: "Some description2",
- description_html: "Some description html2", cached_markdown_version: 4)
- project2 = projects.create!(namespace_id: project_namespace2.id, name: 'gitlab2', path: 'gitlab2',
- project_namespace_id: project_namespace2.id,
- description: "Some description3",
- description_html: "Some description html4", cached_markdown_version: 4)
+ project1 = projects.create!(
+ namespace_id: project_namespace1.id, name: 'gitlab1', path: 'gitlab1',
+ project_namespace_id: project_namespace1.id, description: "Some description2",
+ description_html: "Some description html2", cached_markdown_version: 4
+ )
+ project2 = projects.create!(
+ namespace_id: project_namespace2.id, name: 'gitlab2', path: 'gitlab2',
+ project_namespace_id: project_namespace2.id,
+ description: "Some description3",
+ description_html: "Some description html4", cached_markdown_version: 4
+ )
namespace_details.delete_all
diff --git a/spec/lib/gitlab/background_migration/backfill_releases_author_id_spec.rb b/spec/lib/gitlab/background_migration/backfill_releases_author_id_spec.rb
index d8ad10849f2..898f241a930 100644
--- a/spec/lib/gitlab/background_migration/backfill_releases_author_id_spec.rb
+++ b/spec/lib/gitlab/background_migration/backfill_releases_author_id_spec.rb
@@ -10,35 +10,52 @@ RSpec.describe Gitlab::BackgroundMigration::BackfillReleasesAuthorId,
let!(:test_user) { user_table.create!(name: 'test', email: 'test@example.com', username: 'test', projects_limit: 10) }
let!(:ghost_user) do
- user_table.create!(name: 'ghost', email: 'ghost@example.com',
- username: 'ghost', user_type: User::USER_TYPES['ghost'], projects_limit: 100000)
+ user_table.create!(
+ name: 'ghost', email: 'ghost@example.com',
+ username: 'ghost', user_type: User::USER_TYPES['ghost'], projects_limit: 100000
+ )
end
let(:migration) do
- described_class.new(start_id: 1, end_id: 100,
- batch_table: :releases, batch_column: :id,
- sub_batch_size: 10, pause_ms: 0,
- job_arguments: [ghost_user.id],
- connection: ApplicationRecord.connection)
+ described_class.new(
+ start_id: 1, end_id: 100,
+ batch_table: :releases, batch_column: :id,
+ sub_batch_size: 10, pause_ms: 0,
+ job_arguments: [ghost_user.id],
+ connection: ApplicationRecord.connection
+ )
end
subject(:perform_migration) { migration.perform }
before do
- releases_table.create!(tag: 'tag1', name: 'tag1',
- released_at: (date_time - 1.minute), author_id: test_user.id)
- releases_table.create!(tag: 'tag2', name: 'tag2',
- released_at: (date_time - 2.minutes), author_id: test_user.id)
- releases_table.new(tag: 'tag3', name: 'tag3',
- released_at: (date_time - 3.minutes), author_id: nil).save!(validate: false)
- releases_table.new(tag: 'tag4', name: 'tag4',
- released_at: (date_time - 4.minutes), author_id: nil).save!(validate: false)
- releases_table.new(tag: 'tag5', name: 'tag5',
- released_at: (date_time - 5.minutes), author_id: nil).save!(validate: false)
- releases_table.create!(tag: 'tag6', name: 'tag6',
- released_at: (date_time - 6.minutes), author_id: test_user.id)
- releases_table.new(tag: 'tag7', name: 'tag7',
- released_at: (date_time - 7.minutes), author_id: nil).save!(validate: false)
+ releases_table.create!(
+ tag: 'tag1', name: 'tag1', released_at: (date_time - 1.minute), author_id: test_user.id
+ )
+
+ releases_table.create!(
+ tag: 'tag2', name: 'tag2', released_at: (date_time - 2.minutes), author_id: test_user.id
+ )
+
+ releases_table.new(
+ tag: 'tag3', name: 'tag3', released_at: (date_time - 3.minutes), author_id: nil
+ ).save!(validate: false)
+
+ releases_table.new(
+ tag: 'tag4', name: 'tag4', released_at: (date_time - 4.minutes), author_id: nil
+ ).save!(validate: false)
+
+ releases_table.new(
+ tag: 'tag5', name: 'tag5', released_at: (date_time - 5.minutes), author_id: nil
+ ).save!(validate: false)
+
+ releases_table.create!(
+ tag: 'tag6', name: 'tag6', released_at: (date_time - 6.minutes), author_id: test_user.id
+ )
+
+ releases_table.new(
+ tag: 'tag7', name: 'tag7', released_at: (date_time - 7.minutes), author_id: nil
+ ).save!(validate: false)
end
it 'backfills `author_id` for the selected records', :aggregate_failures do
diff --git a/spec/lib/gitlab/background_migration/backfill_snippet_repositories_spec.rb b/spec/lib/gitlab/background_migration/backfill_snippet_repositories_spec.rb
index 4a50d08b2aa..d8874cb811b 100644
--- a/spec/lib/gitlab/background_migration/backfill_snippet_repositories_spec.rb
+++ b/spec/lib/gitlab/background_migration/backfill_snippet_repositories_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Gitlab::BackgroundMigration::BackfillSnippetRepositories, :migration, schema: 20211202041233,
-feature_category: :source_code_management do
+ feature_category: :source_code_management do
let(:gitlab_shell) { Gitlab::Shell.new }
let(:users) { table(:users) }
let(:snippets) { table(:snippets) }
@@ -14,24 +14,28 @@ feature_category: :source_code_management do
let(:user_name) { 'Test' }
let!(:user) do
- users.create!(id: 1,
- email: 'user@example.com',
- projects_limit: 10,
- username: 'test',
- name: user_name,
- state: user_state,
- last_activity_on: 1.minute.ago,
- user_type: user_type,
- confirmed_at: 1.day.ago)
+ users.create!(
+ id: 1,
+ email: 'user@example.com',
+ projects_limit: 10,
+ username: 'test',
+ name: user_name,
+ state: user_state,
+ last_activity_on: 1.minute.ago,
+ user_type: user_type,
+ confirmed_at: 1.day.ago
+ )
end
let!(:migration_bot) do
- users.create!(id: 100,
- email: "noreply+gitlab-migration-bot%s@#{Settings.gitlab.host}",
- user_type: HasUserType::USER_TYPES[:migration_bot],
- name: 'GitLab Migration Bot',
- projects_limit: 10,
- username: 'bot')
+ users.create!(
+ id: 100,
+ email: "noreply+gitlab-migration-bot%s@#{Settings.gitlab.host}",
+ user_type: HasUserType::USER_TYPES[:migration_bot],
+ name: 'GitLab Migration Bot',
+ projects_limit: 10,
+ username: 'bot'
+ )
end
let!(:snippet_with_repo) { snippets.create!(id: 1, type: 'PersonalSnippet', author_id: user.id, file_name: file_name, content: content) }
@@ -260,15 +264,17 @@ feature_category: :source_code_management do
context 'when both user name and snippet file_name are invalid' do
let(:user_name) { '.' }
let!(:other_user) do
- users.create!(id: 2,
- email: 'user2@example.com',
- projects_limit: 10,
- username: 'test2',
- name: 'Test2',
- state: user_state,
- last_activity_on: 1.minute.ago,
- user_type: user_type,
- confirmed_at: 1.day.ago)
+ users.create!(
+ id: 2,
+ email: 'user2@example.com',
+ projects_limit: 10,
+ username: 'test2',
+ name: 'Test2',
+ state: user_state,
+ last_activity_on: 1.minute.ago,
+ user_type: user_type,
+ confirmed_at: 1.day.ago
+ )
end
let!(:invalid_snippet) { snippets.create!(id: 4, type: 'PersonalSnippet', author_id: user.id, file_name: '.', content: content) }
@@ -322,10 +328,12 @@ feature_category: :source_code_management do
end
def raw_repository(snippet)
- Gitlab::Git::Repository.new('default',
- "#{disk_path(snippet)}.git",
- Gitlab::GlRepository::SNIPPET.identifier_for_container(snippet),
- "@snippets/#{snippet.id}")
+ Gitlab::Git::Repository.new(
+ 'default',
+ "#{disk_path(snippet)}.git",
+ Gitlab::GlRepository::SNIPPET.identifier_for_container(snippet),
+ "@snippets/#{snippet.id}"
+ )
end
def hashed_repository(snippet)
diff --git a/spec/lib/gitlab/background_migration/backfill_vulnerability_reads_cluster_agent_spec.rb b/spec/lib/gitlab/background_migration/backfill_vulnerability_reads_cluster_agent_spec.rb
index f642ec8c20d..3f1a57434a7 100644
--- a/spec/lib/gitlab/background_migration/backfill_vulnerability_reads_cluster_agent_spec.rb
+++ b/spec/lib/gitlab/background_migration/backfill_vulnerability_reads_cluster_agent_spec.rb
@@ -4,10 +4,12 @@ require 'spec_helper'
RSpec.describe Gitlab::BackgroundMigration::BackfillVulnerabilityReadsClusterAgent, :migration, schema: 20220525221133 do # rubocop:disable Layout/LineLength
let(:migration) do
- described_class.new(start_id: 1, end_id: 10,
- batch_table: table_name, batch_column: batch_column,
- sub_batch_size: sub_batch_size, pause_ms: pause_ms,
- connection: ApplicationRecord.connection)
+ described_class.new(
+ start_id: 1, end_id: 10,
+ batch_table: table_name, batch_column: batch_column,
+ sub_batch_size: sub_batch_size, pause_ms: pause_ms,
+ connection: ApplicationRecord.connection
+ )
end
let(:users_table) { table(:users) }
diff --git a/spec/lib/gitlab/background_migration/nullify_orphan_runner_id_on_ci_builds_spec.rb b/spec/lib/gitlab/background_migration/nullify_orphan_runner_id_on_ci_builds_spec.rb
index 2f0eef3c399..5b234679e22 100644
--- a/spec/lib/gitlab/background_migration/nullify_orphan_runner_id_on_ci_builds_spec.rb
+++ b/spec/lib/gitlab/background_migration/nullify_orphan_runner_id_on_ci_builds_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Gitlab::BackgroundMigration::NullifyOrphanRunnerIdOnCiBuilds,
- :suppress_gitlab_schemas_validate_connection, migration: :gitlab_ci, schema: 20220223112304 do
+ :suppress_gitlab_schemas_validate_connection, migration: :gitlab_ci, schema: 20220223112304 do
let(:namespaces) { table(:namespaces) }
let(:projects) { table(:projects) }
let(:ci_runners) { table(:ci_runners) }
diff --git a/spec/lib/gitlab/background_migration/prune_stale_project_export_jobs_spec.rb b/spec/lib/gitlab/background_migration/prune_stale_project_export_jobs_spec.rb
index 5150d0ea4b0..3446b9f0676 100644
--- a/spec/lib/gitlab/background_migration/prune_stale_project_export_jobs_spec.rb
+++ b/spec/lib/gitlab/background_migration/prune_stale_project_export_jobs_spec.rb
@@ -10,14 +10,15 @@ RSpec.describe Gitlab::BackgroundMigration::PruneStaleProjectExportJobs, feature
let(:uploads) { table(:project_relation_export_uploads) }
subject(:perform_migration) do
- described_class.new(start_id: 1,
- end_id: 300,
- batch_table: :project_export_jobs,
- batch_column: :id,
- sub_batch_size: 2,
- pause_ms: 0,
- connection: ActiveRecord::Base.connection)
- .perform
+ described_class.new(
+ start_id: 1,
+ end_id: 300,
+ batch_table: :project_export_jobs,
+ batch_column: :id,
+ sub_batch_size: 2,
+ pause_ms: 0,
+ connection: ActiveRecord::Base.connection
+ ).perform
end
it 'removes export jobs and associated relations older than 7 days' do
diff --git a/spec/lib/gitlab/background_migration/remove_backfilled_job_artifacts_expire_at_spec.rb b/spec/lib/gitlab/background_migration/remove_backfilled_job_artifacts_expire_at_spec.rb
index 5fede892463..582c0fe1b1b 100644
--- a/spec/lib/gitlab/background_migration/remove_backfilled_job_artifacts_expire_at_spec.rb
+++ b/spec/lib/gitlab/background_migration/remove_backfilled_job_artifacts_expire_at_spec.rb
@@ -86,8 +86,10 @@ RSpec.describe Gitlab::BackgroundMigration::RemoveBackfilledJobArtifactsExpireAt
def create_job_artifact(id:, file_type:, expire_at:)
job = table(:ci_builds, database: :ci).create!(id: id, partition_id: 100)
- job_artifact.create!(id: id, job_id: job.id, expire_at: expire_at, project_id: project.id,
- file_type: file_type, partition_id: 100)
+ job_artifact.create!(
+ id: id, job_id: job.id, expire_at: expire_at, project_id: project.id,
+ file_type: file_type, partition_id: 100
+ )
end
end
end
diff --git a/spec/lib/gitlab/background_migration/remove_occurrence_pipelines_and_duplicate_vulnerabilities_findings_spec.rb b/spec/lib/gitlab/background_migration/remove_occurrence_pipelines_and_duplicate_vulnerabilities_findings_spec.rb
index 1844347f4a9..60ee61cf50a 100644
--- a/spec/lib/gitlab/background_migration/remove_occurrence_pipelines_and_duplicate_vulnerabilities_findings_spec.rb
+++ b/spec/lib/gitlab/background_migration/remove_occurrence_pipelines_and_duplicate_vulnerabilities_findings_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe Gitlab::BackgroundMigration::RemoveOccurrencePipelinesAndDuplicateVulnerabilitiesFindings, :migration,
- :suppress_gitlab_schemas_validate_connection, schema: 20220326161803 do
+ :suppress_gitlab_schemas_validate_connection, schema: 20220326161803 do
let(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
let(:users) { table(:users) }
let(:user) { create_user! }
diff --git a/spec/lib/gitlab/background_migration/remove_self_managed_wiki_notes_spec.rb b/spec/lib/gitlab/background_migration/remove_self_managed_wiki_notes_spec.rb
index 81927100562..59d5d56ebe8 100644
--- a/spec/lib/gitlab/background_migration/remove_self_managed_wiki_notes_spec.rb
+++ b/spec/lib/gitlab/background_migration/remove_self_managed_wiki_notes_spec.rb
@@ -6,14 +6,15 @@ RSpec.describe Gitlab::BackgroundMigration::RemoveSelfManagedWikiNotes, :migrati
let(:notes) { table(:notes) }
subject(:perform_migration) do
- described_class.new(start_id: 1,
- end_id: 30,
- batch_table: :notes,
- batch_column: :id,
- sub_batch_size: 2,
- pause_ms: 0,
- connection: ActiveRecord::Base.connection)
- .perform
+ described_class.new(
+ start_id: 1,
+ end_id: 30,
+ batch_table: :notes,
+ batch_column: :id,
+ sub_batch_size: 2,
+ pause_ms: 0,
+ connection: ActiveRecord::Base.connection
+ ).perform
end
it 'removes all wiki notes' do
diff --git a/spec/lib/gitlab/background_migration/reset_too_many_tags_skipped_registry_imports_spec.rb b/spec/lib/gitlab/background_migration/reset_too_many_tags_skipped_registry_imports_spec.rb
index 3f59b0a24a3..afdd855c5a8 100644
--- a/spec/lib/gitlab/background_migration/reset_too_many_tags_skipped_registry_imports_spec.rb
+++ b/spec/lib/gitlab/background_migration/reset_too_many_tags_skipped_registry_imports_spec.rb
@@ -3,8 +3,8 @@
require 'spec_helper'
RSpec.describe Gitlab::BackgroundMigration::ResetTooManyTagsSkippedRegistryImports, :migration,
- :aggregate_failures,
- schema: 20220502173045 do
+ :aggregate_failures,
+ schema: 20220502173045 do
let(:namespaces) { table(:namespaces) }
let(:projects) { table(:projects) }
let(:container_repositories) { table(:container_repositories) }
@@ -15,46 +15,54 @@ RSpec.describe Gitlab::BackgroundMigration::ResetTooManyTagsSkippedRegistryImpor
let!(:project) { projects.create!(id: 1, project_namespace_id: 1, namespace_id: 1, path: 'bar', name: 'bar') }
let!(:container_repository1) do
- container_repositories.create!(id: 1,
- project_id: 1,
- name: 'a',
- migration_state: 'import_skipped',
- migration_skipped_at: Time.zone.now,
- migration_skipped_reason: 2,
- migration_pre_import_started_at: Time.zone.now,
- migration_pre_import_done_at: Time.zone.now,
- migration_import_started_at: Time.zone.now,
- migration_import_done_at: Time.zone.now,
- migration_aborted_at: Time.zone.now,
- migration_retries_count: 2,
- migration_aborted_in_state: 'importing')
+ container_repositories.create!(
+ id: 1,
+ project_id: 1,
+ name: 'a',
+ migration_state: 'import_skipped',
+ migration_skipped_at: Time.zone.now,
+ migration_skipped_reason: 2,
+ migration_pre_import_started_at: Time.zone.now,
+ migration_pre_import_done_at: Time.zone.now,
+ migration_import_started_at: Time.zone.now,
+ migration_import_done_at: Time.zone.now,
+ migration_aborted_at: Time.zone.now,
+ migration_retries_count: 2,
+ migration_aborted_in_state: 'importing'
+ )
end
let!(:container_repository2) do
- container_repositories.create!(id: 2,
- project_id: 1,
- name: 'b',
- migration_state: 'import_skipped',
- migration_skipped_at: Time.zone.now,
- migration_skipped_reason: 2)
+ container_repositories.create!(
+ id: 2,
+ project_id: 1,
+ name: 'b',
+ migration_state: 'import_skipped',
+ migration_skipped_at: Time.zone.now,
+ migration_skipped_reason: 2
+ )
end
let!(:container_repository3) do
- container_repositories.create!(id: 3,
- project_id: 1,
- name: 'c',
- migration_state: 'import_skipped',
- migration_skipped_at: Time.zone.now,
- migration_skipped_reason: 1)
+ container_repositories.create!(
+ id: 3,
+ project_id: 1,
+ name: 'c',
+ migration_state: 'import_skipped',
+ migration_skipped_at: Time.zone.now,
+ migration_skipped_reason: 1
+ )
end
# This is an unlikely state, but included here to test the edge case
let!(:container_repository4) do
- container_repositories.create!(id: 4,
- project_id: 1,
- name: 'd',
- migration_state: 'default',
- migration_skipped_reason: 2)
+ container_repositories.create!(
+ id: 4,
+ project_id: 1,
+ name: 'd',
+ migration_state: 'default',
+ migration_skipped_reason: 2
+ )
end
describe '#up' do
diff --git a/spec/lib/gitlab/background_migration/set_correct_vulnerability_state_spec.rb b/spec/lib/gitlab/background_migration/set_correct_vulnerability_state_spec.rb
index 2372ce21c4c..df1ee494987 100644
--- a/spec/lib/gitlab/background_migration/set_correct_vulnerability_state_spec.rb
+++ b/spec/lib/gitlab/background_migration/set_correct_vulnerability_state_spec.rb
@@ -35,13 +35,15 @@ RSpec.describe Gitlab::BackgroundMigration::SetCorrectVulnerabilityState do
let(:dismissed_state) { 2 }
let(:migration_job) do
- described_class.new(start_id: vulnerability_with_dismissed_at.id,
- end_id: vulnerability_without_dismissed_at.id,
- batch_table: :vulnerabilities,
- batch_column: :id,
- sub_batch_size: 1,
- pause_ms: 0,
- connection: ActiveRecord::Base.connection)
+ described_class.new(
+ start_id: vulnerability_with_dismissed_at.id,
+ end_id: vulnerability_without_dismissed_at.id,
+ batch_table: :vulnerabilities,
+ batch_column: :id,
+ sub_batch_size: 1,
+ pause_ms: 0,
+ connection: ActiveRecord::Base.connection
+ )
end
describe '#filter_batch' do
diff --git a/spec/lib/gitlab/background_migration/set_legacy_open_source_license_available_for_non_public_projects_spec.rb b/spec/lib/gitlab/background_migration/set_legacy_open_source_license_available_for_non_public_projects_spec.rb
index e9f73672144..5109c3ec0c2 100644
--- a/spec/lib/gitlab/background_migration/set_legacy_open_source_license_available_for_non_public_projects_spec.rb
+++ b/spec/lib/gitlab/background_migration/set_legacy_open_source_license_available_for_non_public_projects_spec.rb
@@ -3,21 +3,22 @@
require 'spec_helper'
RSpec.describe Gitlab::BackgroundMigration::SetLegacyOpenSourceLicenseAvailableForNonPublicProjects,
- :migration,
- schema: 20220722110026 do
+ :migration,
+ schema: 20220722110026 do
let(:namespaces_table) { table(:namespaces) }
let(:projects_table) { table(:projects) }
let(:project_settings_table) { table(:project_settings) }
subject(:perform_migration) do
- described_class.new(start_id: projects_table.minimum(:id),
- end_id: projects_table.maximum(:id),
- batch_table: :projects,
- batch_column: :id,
- sub_batch_size: 2,
- pause_ms: 0,
- connection: ActiveRecord::Base.connection)
- .perform
+ described_class.new(
+ start_id: projects_table.minimum(:id),
+ end_id: projects_table.maximum(:id),
+ batch_table: :projects,
+ batch_column: :id,
+ sub_batch_size: 2,
+ pause_ms: 0,
+ connection: ActiveRecord::Base.connection
+ ).perform
end
it 'sets `legacy_open_source_license_available` attribute to false for non-public projects', :aggregate_failures do
@@ -37,11 +38,13 @@ RSpec.describe Gitlab::BackgroundMigration::SetLegacyOpenSourceLicenseAvailableF
def create_legacy_license_project(path, visibility_level:)
namespace = namespaces_table.create!(name: "namespace-#{path}", path: "namespace-#{path}")
project_namespace = namespaces_table.create!(name: "project-namespace-#{path}", path: path, type: 'Project')
- project = projects_table.create!(name: path,
- path: path,
- namespace_id: namespace.id,
- project_namespace_id: project_namespace.id,
- visibility_level: visibility_level)
+ project = projects_table.create!(
+ name: path,
+ path: path,
+ namespace_id: namespace.id,
+ project_namespace_id: project_namespace.id,
+ visibility_level: visibility_level
+ )
project_settings_table.create!(project_id: project.id, legacy_open_source_license_available: true)
project
diff --git a/spec/lib/gitlab/background_migration/update_delayed_project_removal_to_null_for_user_namespaces_spec.rb b/spec/lib/gitlab/background_migration/update_delayed_project_removal_to_null_for_user_namespaces_spec.rb
index 980a7771f4c..0579a299c74 100644
--- a/spec/lib/gitlab/background_migration/update_delayed_project_removal_to_null_for_user_namespaces_spec.rb
+++ b/spec/lib/gitlab/background_migration/update_delayed_project_removal_to_null_for_user_namespaces_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Gitlab::BackgroundMigration::UpdateDelayedProjectRemovalToNullForUserNamespaces,
- :migration do
+ :migration do
let(:namespaces_table) { table(:namespaces) }
let(:namespace_settings_table) { table(:namespace_settings) }
diff --git a/spec/lib/gitlab/background_migration/update_jira_tracker_data_deployment_type_based_on_url_spec.rb b/spec/lib/gitlab/background_migration/update_jira_tracker_data_deployment_type_based_on_url_spec.rb
index c090c1df424..75fe5699986 100644
--- a/spec/lib/gitlab/background_migration/update_jira_tracker_data_deployment_type_based_on_url_spec.rb
+++ b/spec/lib/gitlab/background_migration/update_jira_tracker_data_deployment_type_based_on_url_spec.rb
@@ -13,10 +13,12 @@ RSpec.describe Gitlab::BackgroundMigration::UpdateJiraTrackerDataDeploymentTypeB
let(:sub_batch_size) { 1 }
let(:pause_ms) { 0 }
let(:migration) do
- described_class.new(start_id: 1, end_id: 10,
- batch_table: table_name, batch_column: batch_column,
- sub_batch_size: sub_batch_size, pause_ms: pause_ms,
- connection: ApplicationRecord.connection)
+ described_class.new(
+ start_id: 1, end_id: 10,
+ batch_table: table_name, batch_column: batch_column,
+ sub_batch_size: sub_batch_size, pause_ms: pause_ms,
+ connection: ApplicationRecord.connection
+ )
end
subject(:perform_migration) do
diff --git a/spec/lib/gitlab/data_builder/deployment_spec.rb b/spec/lib/gitlab/data_builder/deployment_spec.rb
index bf08e782035..82ec3e791a4 100644
--- a/spec/lib/gitlab/data_builder/deployment_spec.rb
+++ b/spec/lib/gitlab/data_builder/deployment_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::DataBuilder::Deployment do
+RSpec.describe Gitlab::DataBuilder::Deployment, feature_category: :continuous_delivery do
describe '.build' do
it 'returns the object kind for a deployment' do
deployment = build(:deployment, deployable: nil, environment: create(:environment))
@@ -40,6 +40,7 @@ RSpec.describe Gitlab::DataBuilder::Deployment do
expect(data[:commit_url]).to eq(expected_commit_url)
expect(data[:commit_title]).to eq(commit.title)
expect(data[:ref]).to eq(deployment.ref)
+ expect(data[:environment_tier]).to eq('other')
end
it 'does not include the deployable URL when there is no deployable' do
diff --git a/spec/lib/gitlab/database/migrations/instrumentation_spec.rb b/spec/lib/gitlab/database/migrations/instrumentation_spec.rb
index 4f347034c0b..0b25389c667 100644
--- a/spec/lib/gitlab/database/migrations/instrumentation_spec.rb
+++ b/spec/lib/gitlab/database/migrations/instrumentation_spec.rb
@@ -18,7 +18,9 @@ RSpec.describe Gitlab::Database::Migrations::Instrumentation do
let(:migration_name) { 'test' }
let(:migration_version) { '12345' }
let(:migration_meta) { { 'max_batch_size' => 1, 'total_tuple_count' => 10, 'interval' => 60 } }
- let(:expected_json_keys) { %w[version name walltime success total_database_size_change query_statistics] }
+ let(:expected_json_keys) do
+ %w[version name walltime success total_database_size_change query_statistics error_message]
+ end
it 'executes the given block' do
expect do |b|
@@ -90,16 +92,14 @@ RSpec.describe Gitlab::Database::Migrations::Instrumentation do
end
context 'upon failure' do
- where(exception: ['something went wrong', SystemStackError, Interrupt])
+ where(:exception, :error_message) do
+ [[StandardError, 'something went wrong'], [ActiveRecord::StatementTimeout, 'timeout']]
+ end
with_them do
subject(:observe) do
instrumentation.observe(version: migration_version, name: migration_name,
- connection: connection, meta: migration_meta) { raise exception }
- end
-
- it 'raises the exception' do
- expect { observe }.to raise_error(exception)
+ connection: connection, meta: migration_meta) { raise exception, error_message }
end
context 'retrieving observations' do
@@ -107,10 +107,6 @@ RSpec.describe Gitlab::Database::Migrations::Instrumentation do
before do
observe
- # rubocop:disable Lint/RescueException
- rescue Exception
- # rubocop:enable Lint/RescueException
- # ignore (we expect this exception)
end
it 'records a valid observation', :aggregate_failures do
@@ -118,6 +114,7 @@ RSpec.describe Gitlab::Database::Migrations::Instrumentation do
expect(subject['success']).to be_falsey
expect(subject['version']).to eq(migration_version)
expect(subject['name']).to eq(migration_name)
+ expect(subject['error_message']).to eq(error_message)
end
it 'transforms observation to expected json' do
diff --git a/spec/lib/gitlab/database/schema_validation/inconsistency_spec.rb b/spec/lib/gitlab/database/schema_validation/inconsistency_spec.rb
index cb3df75b3fb..a49ff8339a1 100644
--- a/spec/lib/gitlab/database/schema_validation/inconsistency_spec.rb
+++ b/spec/lib/gitlab/database/schema_validation/inconsistency_spec.rb
@@ -50,6 +50,32 @@ RSpec.describe Gitlab::Database::SchemaValidation::Inconsistency, feature_catego
end
end
+ describe '#object_type' do
+ it 'returns the structure sql object type' do
+ expect(inconsistency.object_type).to eq('Index')
+ end
+
+ context 'when the structure sql object is not available' do
+ subject(:inconsistency) { described_class.new(validator, nil, database_object) }
+
+ it 'returns the database object type' do
+ expect(inconsistency.object_type).to eq('Index')
+ end
+ end
+ end
+
+ describe '#structure_sql_statement' do
+ it 'returns structure sql statement' do
+ expect(inconsistency.structure_sql_statement).to eq("#{structure_sql_statement}\n")
+ end
+ end
+
+ describe '#database_statement' do
+ it 'returns database statement' do
+ expect(inconsistency.database_statement).to eq("#{database_statement}\n")
+ end
+ end
+
describe '#inspect' do
let(:expected_output) do
<<~MSG
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index 8a2602ea9f6..34f9948b9dc 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -647,6 +647,7 @@ project:
- redirect_routes
- statistics
- container_repositories
+- container_registry_data_repair_detail
- uploads
- file_uploads
- import_state
diff --git a/spec/models/blob_viewer/metrics_dashboard_yml_spec.rb b/spec/models/blob_viewer/metrics_dashboard_yml_spec.rb
index d28fa0bbe97..c9ac13eefc0 100644
--- a/spec/models/blob_viewer/metrics_dashboard_yml_spec.rb
+++ b/spec/models/blob_viewer/metrics_dashboard_yml_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe BlobViewer::MetricsDashboardYml do
+RSpec.describe BlobViewer::MetricsDashboardYml, feature_category: :metrics do
include FakeBlobHelpers
include RepoHelpers
@@ -119,4 +119,18 @@ RSpec.describe BlobViewer::MetricsDashboardYml do
expect(viewer.errors).to eq ["YAML syntax: The parsed YAML is too big"]
end
end
+
+ describe '.can_render?' do
+ subject { described_class.can_render?(blob) }
+
+ it { is_expected.to be false }
+
+ context 'when metrics dashboard feature is available' do
+ before do
+ stub_feature_flags(remove_monitor_metrics: false)
+ end
+
+ it { is_expected.to be true }
+ end
+ end
end
diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb
index df630d6336c..edb856d34df 100644
--- a/spec/models/commit_spec.rb
+++ b/spec/models/commit_spec.rb
@@ -885,4 +885,94 @@ eos
expect(commit.has_been_reverted?(user, issue.notes_with_associations)).to eq(false)
end
end
+
+ describe '#tipping_refs' do
+ let_it_be(:tag_name) { 'v1.1.0' }
+ let_it_be(:branch_names) { %w[master not-merged-branch v1.1.0] }
+
+ shared_examples 'tipping ref names' do
+ context 'when called without limits' do
+ it 'return tipping refs names' do
+ expect(called_method.call).to eq(expected)
+ end
+ end
+
+ context 'when called with limits' do
+ it 'return tipping refs names' do
+ limit = 1
+ expect(called_method.call(limit).size).to be <= limit
+ end
+ end
+
+ describe '#tipping_branches' do
+ let(:called_method) { ->(limit = 0) { commit.tipping_branches(limit: limit) } }
+ let(:expected) { branch_names }
+
+ it_behaves_like 'with tipping ref names'
+ end
+
+ describe '#tipping_tags' do
+ let(:called_method) { ->(limit = 0) { commit.tipping_tags(limit: limit) } }
+ let(:expected) { [tag_name] }
+
+ it_behaves_like 'with tipping ref names'
+ end
+ end
+ end
+
+ context 'containing refs' do
+ shared_examples 'containing ref names' do
+ context 'without arguments' do
+ it 'returns branch names containing the commit' do
+ expect(ref_containing.call).to eq(containing_refs)
+ end
+ end
+
+ context 'with limit argument' do
+ it 'returns the appropriate amount branch names' do
+ limit = 2
+ expect(ref_containing.call(limit: limit).size).to be <= limit
+ end
+ end
+
+ context 'with tipping refs excluded' do
+ let(:excluded_refs) do
+ project.repository.refs_by_oid(oid: commit_sha, ref_patterns: [ref_prefix]).map { |n| n.delete_prefix(ref_prefix) }
+ end
+
+ it 'returns branch names containing the commit without the one with the commit at tip' do
+ expect(ref_containing.call(excluded_tipped: true)).to eq(containing_refs - excluded_refs)
+ end
+
+ it 'returns the appropriate amount branch names with limit argument' do
+ limit = 2
+ expect(ref_containing.call(limit: limit, excluded_tipped: true).size).to be <= limit
+ end
+ end
+ end
+
+ describe '#branches_containing' do
+ let_it_be(:commit_sha) { project.commit.sha }
+ let_it_be(:containing_refs) { project.repository.branch_names_contains(commit_sha) }
+
+ let(:ref_prefix) { Gitlab::Git::BRANCH_REF_PREFIX }
+
+ let(:ref_containing) { ->(limit: 0, excluded_tipped: false) { commit.branches_containing(exclude_tipped: excluded_tipped, limit: limit) } }
+
+ it_behaves_like 'containing ref names'
+ end
+
+ describe '#tags_containing' do
+ let_it_be(:tag_name) { 'v1.1.0' }
+ let_it_be(:commit_sha) { project.repository.find_tag(tag_name).target_commit.sha }
+ let_it_be(:containing_refs) { %w[v1.1.0 v1.1.1] }
+
+ let(:ref_prefix) { Gitlab::Git::TAG_REF_PREFIX }
+
+ let(:commit) { project.repository.commit(commit_sha) }
+ let(:ref_containing) { ->(limit: 0, excluded_tipped: false) { commit.tags_containing(exclude_tipped: excluded_tipped, limit: limit) } }
+
+ it_behaves_like 'containing ref names'
+ end
+ end
end
diff --git a/spec/models/container_registry/data_repair_detail_spec.rb b/spec/models/container_registry/data_repair_detail_spec.rb
index 92833553a1e..4d2ac5fff42 100644
--- a/spec/models/container_registry/data_repair_detail_spec.rb
+++ b/spec/models/container_registry/data_repair_detail_spec.rb
@@ -8,4 +8,22 @@ RSpec.describe ContainerRegistry::DataRepairDetail, type: :model, feature_catego
subject { described_class.new(project: project) }
it { is_expected.to belong_to(:project).required }
+
+ it_behaves_like 'having unique enum values'
+
+ describe '.ongoing_since' do
+ let_it_be(:repair_detail1) { create(:container_registry_data_repair_detail, :ongoing, updated_at: 1.day.ago) }
+ let_it_be(:repair_detail2) { create(:container_registry_data_repair_detail, :ongoing, updated_at: 20.minutes.ago) }
+ let_it_be(:repair_detail3) do
+ create(:container_registry_data_repair_detail, :completed, updated_at: 20.minutes.ago)
+ end
+
+ let_it_be(:repair_detail4) do
+ create(:container_registry_data_repair_detail, :completed, updated_at: 31.minutes.ago)
+ end
+
+ subject { described_class.ongoing_since(30.minutes.ago) }
+
+ it { is_expected.to contain_exactly(repair_detail1) }
+ end
end
diff --git a/spec/models/milestone_spec.rb b/spec/models/milestone_spec.rb
index 8bd7c057a6e..1c43eafb576 100644
--- a/spec/models/milestone_spec.rb
+++ b/spec/models/milestone_spec.rb
@@ -724,4 +724,12 @@ RSpec.describe Milestone do
end
end
end
+
+ describe '#lock_version' do
+ let_it_be(:milestone) { create(:milestone, project: project) }
+
+ it 'ensures that lock_version and optimistic locking is enabled' do
+ expect(milestone.lock_version).to be_present
+ end
+ end
end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 855c5f66554..e9bb01f4b23 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -95,6 +95,7 @@ RSpec.describe Project, factory_default: :keep, feature_category: :projects do
it { is_expected.to have_one(:mock_ci_integration) }
it { is_expected.to have_one(:mock_monitoring_integration) }
it { is_expected.to have_one(:service_desk_custom_email_verification).class_name('ServiceDesk::CustomEmailVerification') }
+ it { is_expected.to have_one(:container_registry_data_repair_detail).class_name('ContainerRegistry::DataRepairDetail') }
it { is_expected.to have_many(:commit_statuses) }
it { is_expected.to have_many(:ci_pipelines) }
it { is_expected.to have_many(:ci_refs) }
@@ -6800,6 +6801,19 @@ RSpec.describe Project, factory_default: :keep, feature_category: :projects do
end
end
+ describe '.pending_data_repair_analysis' do
+ it 'returns projects that are not in ContainerRegistry::DataRepairDetail' do
+ project_1 = create(:project)
+ project_2 = create(:project)
+
+ expect(described_class.pending_data_repair_analysis).to match_array([project_1, project_2])
+
+ create(:container_registry_data_repair_detail, project: project_1)
+
+ expect(described_class.pending_data_repair_analysis).to match_array([project_2])
+ end
+ end
+
describe '.deployments' do
subject { project.deployments }
diff --git a/spec/requests/api/graphql/metrics/dashboard/annotations_spec.rb b/spec/requests/api/graphql/metrics/dashboard/annotations_spec.rb
index a3103b1af57..143bc1672f8 100644
--- a/spec/requests/api/graphql/metrics/dashboard/annotations_spec.rb
+++ b/spec/requests/api/graphql/metrics/dashboard/annotations_spec.rb
@@ -22,6 +22,7 @@ RSpec.describe 'Getting Metrics Dashboard Annotations', feature_category: :metri
create(:metrics_dashboard_annotation, environment: environment, starting_at: to.advance(minutes: 5), dashboard_path: path)
end
+ let(:remove_monitor_metrics) { false }
let(:args) { "from: \"#{from}\", to: \"#{to}\"" }
let(:fields) do
<<~QUERY
@@ -50,7 +51,7 @@ RSpec.describe 'Getting Metrics Dashboard Annotations', feature_category: :metri
end
before do
- stub_feature_flags(remove_monitor_metrics: false)
+ stub_feature_flags(remove_monitor_metrics: remove_monitor_metrics)
project.add_developer(current_user)
post_graphql(query, current_user: current_user)
end
@@ -86,4 +87,18 @@ RSpec.describe 'Getting Metrics Dashboard Annotations', feature_category: :metri
it_behaves_like 'a working graphql query'
end
end
+
+ context 'when metrics dashboard feature is unavailable' do
+ let(:remove_monitor_metrics) { true }
+
+ it_behaves_like 'a working graphql query'
+
+ it 'returns nil' do
+ annotations = graphql_data.dig(
+ 'project', 'environments', 'nodes', 0, 'metricsDashboard', 'annotations'
+ )
+
+ expect(annotations).to be_nil
+ end
+ end
end
diff --git a/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/create_spec.rb b/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/create_spec.rb
index 3c7f4a030f9..d81744abe1b 100644
--- a/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/create_spec.rb
+++ b/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/create_spec.rb
@@ -19,6 +19,10 @@ RSpec.describe Mutations::Metrics::Dashboard::Annotations::Create, feature_categ
graphql_mutation_response(:create_annotation)
end
+ before do
+ stub_feature_flags(remove_monitor_metrics: false)
+ end
+
specify { expect(described_class).to require_graphql_authorizations(:admin_metrics_dashboard_annotation) }
context 'when annotation source is environment' do
@@ -103,6 +107,15 @@ RSpec.describe Mutations::Metrics::Dashboard::Annotations::Create, feature_categ
it_behaves_like 'an invalid argument to the mutation', argument_name: :environment_id
end
+
+ context 'when metrics dashboard feature is unavailable' do
+ before do
+ stub_feature_flags(remove_monitor_metrics: true)
+ end
+
+ it_behaves_like 'a mutation that returns top-level errors',
+ errors: [Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR]
+ end
end
end
diff --git a/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/delete_spec.rb b/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/delete_spec.rb
index c104138b725..09977cd19d7 100644
--- a/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/delete_spec.rb
+++ b/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/delete_spec.rb
@@ -17,6 +17,10 @@ RSpec.describe Mutations::Metrics::Dashboard::Annotations::Delete, feature_categ
graphql_mutation_response(:delete_annotation)
end
+ before do
+ stub_feature_flags(remove_monitor_metrics: false)
+ end
+
specify { expect(described_class).to require_graphql_authorizations(:admin_metrics_dashboard_annotation) }
context 'when the user has permission to delete the annotation' do
@@ -54,6 +58,15 @@ RSpec.describe Mutations::Metrics::Dashboard::Annotations::Delete, feature_categ
expect(mutation_response['errors']).to eq([service_response[:message]])
end
end
+
+ context 'when metrics dashboard feature is unavailable' do
+ before do
+ stub_feature_flags(remove_monitor_metrics: true)
+ end
+
+ it_behaves_like 'a mutation that returns top-level errors',
+ errors: [Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR]
+ end
end
context 'when the user does not have permission to delete the annotation' do
diff --git a/spec/requests/api/graphql/project/branches_tipping_at_commit_spec.rb b/spec/requests/api/graphql/project/branches_tipping_at_commit_spec.rb
deleted file mode 100644
index bba8977078d..00000000000
--- a/spec/requests/api/graphql/project/branches_tipping_at_commit_spec.rb
+++ /dev/null
@@ -1,67 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'Query.project(fullPath).tagsTippingAtCommit(commitSha)', feature_category: :source_code_management do
- include GraphqlHelpers
- include Presentable
-
- let_it_be(:project) { create(:project, :repository) }
- let_it_be(:repository) { project.repository.raw }
- let_it_be(:current_user) { project.first_owner }
- let_it_be(:branches_names) { %w[master not-merged-branch v1.1.0] }
-
- let(:post_query) { post_graphql(query, current_user: current_user) }
- let(:path) { %w[project branchesTippingAtCommit names] }
- let(:data) { graphql_data.dig(*path) }
-
- let(:query) do
- graphql_query_for(
- :project,
- { fullPath: project.full_path },
- query_graphql_field(:branchesTippingAtCommit, { commitSha: commit_sha }, :names)
- )
- end
-
- context 'when commit exists and is tipping branches' do
- let_it_be(:commit_sha) { repository.commit.id }
-
- context 'with authorized user' do
- it 'returns branches names tipping the commit' do
- post_query
-
- expect(data).to eq(branches_names)
- end
- end
-
- context 'when user is not authorized' do
- let(:current_user) { create(:user) }
-
- it 'returns branches names tipping the commit' do
- post_query
-
- expect(data).to eq(nil)
- end
- end
- end
-
- context 'when commit does not exist' do
- let(:commit_sha) { '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff4' }
-
- it 'returns tags names tipping the commit' do
- post_query
-
- expect(data).to eq([])
- end
- end
-
- context 'when commit exists but does not tip any branches' do
- let(:commit_sha) { project.repository.commits(nil, { limit: 4 }).commits[2].id }
-
- it 'returns tags names tipping the commit' do
- post_query
-
- expect(data).to eq([])
- end
- end
-end
diff --git a/spec/requests/api/graphql/project/commit_references_spec.rb b/spec/requests/api/graphql/project/commit_references_spec.rb
new file mode 100644
index 00000000000..4b545adee12
--- /dev/null
+++ b/spec/requests/api/graphql/project/commit_references_spec.rb
@@ -0,0 +1,240 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Query.project(fullPath).commitReferences(commitSha)', feature_category: :source_code_management do
+ include GraphqlHelpers
+ include Presentable
+
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:repository) { project.repository.raw }
+ let_it_be(:current_user) { project.first_owner }
+ let_it_be(:branches_names) { %w[master not-merged-branch v1.1.0] }
+ let_it_be(:tag_name) { 'v1.0.0' }
+ let_it_be(:commit_sha) { repository.commit.id }
+
+ let(:post_query) { post_graphql(query, current_user: current_user) }
+ let(:data) { graphql_data.dig(*path) }
+ let(:base_args) { {} }
+ let(:args) { base_args }
+
+ shared_context 'with the limit argument' do
+ context 'with limit of 2' do
+ let(:args) { { limit: 2 } }
+
+ it 'returns the right amount of refs' do
+ post_query
+ expect(data.count).to be <= 2
+ end
+ end
+
+ context 'with limit of -2' do
+ let(:args) { { limit: -2 } }
+
+ it 'casts an argument error "limit must be greater then 0"' do
+ post_query
+ expect(graphql_errors).to include(custom_graphql_error(path - ['names'],
+ 'limit must be within 1..1000'))
+ end
+ end
+
+ context 'with limit of 1001' do
+ let(:args) { { limit: 1001 } }
+
+ it 'casts an argument error "limit must be greater then 0"' do
+ post_query
+ expect(graphql_errors).to include(custom_graphql_error(path - ['names'],
+ 'limit must be within 1..1000'))
+ end
+ end
+ end
+
+ describe 'the path commitReferences should return nil' do
+ let(:path) { %w[project commitReferences] }
+
+ let(:query) do
+ graphql_query_for(:project, { fullPath: project.full_path },
+ query_graphql_field(
+ :commitReferences,
+ { commitSha: commit_sha },
+ query_graphql_field(:tippingTags, :names)
+ )
+ )
+ end
+
+ context 'when commit does not exist' do
+ let(:commit_sha) { '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff4' }
+
+ it 'commitReferences returns nil' do
+ post_query
+ expect(data).to eq(nil)
+ end
+ end
+
+ context 'when sha length is incorrect' do
+ let(:commit_sha) { 'foo' }
+
+ it 'commitReferences returns nil' do
+ post_query
+ expect(data).to eq(nil)
+ end
+ end
+
+ context 'when user is not authorized' do
+ let(:commit_sha) { repository.commit.id }
+ let(:current_user) { create(:user) }
+
+ it 'commitReferences returns nil' do
+ post_query
+ expect(data).to eq(nil)
+ end
+ end
+ end
+
+ context 'with containing refs' do
+ let(:base_args) { { excludeTipped: false } }
+ let(:excluded_tipped_args) do
+ hash = base_args.dup
+ hash[:excludeTipped] = true
+ hash
+ end
+
+ context 'with path Query.project(fullPath).commitReferences(commitSha).containingTags' do
+ let_it_be(:commit_sha) { repository.find_tag(tag_name).target_commit.sha }
+ let_it_be(:path) { %w[project commitReferences containingTags names] }
+ let(:query) do
+ graphql_query_for(
+ :project,
+ { fullPath: project.full_path },
+ query_graphql_field(
+ :commitReferences,
+ { commitSha: commit_sha },
+ query_graphql_field(:containingTags, args, :names)
+ )
+ )
+ end
+
+ context 'without excludeTipped argument' do
+ it 'returns tags names containing the commit' do
+ post_query
+ expect(data).to eq(%w[v1.0.0 v1.1.0 v1.1.1])
+ end
+ end
+
+ context 'with excludeTipped argument' do
+ let_it_be(:ref_prefix) { Gitlab::Git::TAG_REF_PREFIX }
+
+ let(:args) { excluded_tipped_args }
+
+ it 'returns tags names containing the commit without the tipped tags' do
+ excluded_refs = project.repository
+ .refs_by_oid(oid: commit_sha, ref_patterns: [ref_prefix])
+ .map { |n| n.delete_prefix(ref_prefix) }
+
+ post_query
+ expect(data).to eq(%w[v1.0.0 v1.1.0 v1.1.1] - excluded_refs)
+ end
+ end
+
+ include_context 'with the limit argument'
+ end
+
+ context 'with path Query.project(fullPath).commitReferences(commitSha).containingBranches' do
+ let_it_be(:ref_prefix) { Gitlab::Git::BRANCH_REF_PREFIX }
+ let_it_be(:path) { %w[project commitReferences containingBranches names] }
+
+ let(:query) do
+ graphql_query_for(
+ :project,
+ { fullPath: project.full_path },
+ query_graphql_field(
+ :commitReferences,
+ { commitSha: commit_sha },
+ query_graphql_field(:containingBranches, args, :names)
+ )
+ )
+ end
+
+ context 'without excludeTipped argument' do
+ it 'returns branch names containing the commit' do
+ refs = project.repository.branch_names_contains(commit_sha)
+
+ post_query
+
+ expect(data).to eq(refs)
+ end
+ end
+
+ context 'with excludeTipped argument' do
+ let(:args) { excluded_tipped_args }
+
+ it 'returns branch names containing the commit without the tipped branch' do
+ refs = project.repository.branch_names_contains(commit_sha)
+
+ excluded_refs = project.repository
+ .refs_by_oid(oid: commit_sha, ref_patterns: [ref_prefix])
+ .map { |n| n.delete_prefix(ref_prefix) }
+
+ post_query
+
+ expect(data).to eq(refs - excluded_refs)
+ end
+ end
+
+ include_context 'with the limit argument'
+ end
+ end
+
+ context 'with tipping refs' do
+ context 'with path Query.project(fullPath).commitReferences(commitSha).tippingTags' do
+ let(:commit_sha) { repository.find_tag(tag_name).dereferenced_target.sha }
+ let(:path) { %w[project commitReferences tippingTags names] }
+
+ let(:query) do
+ graphql_query_for(
+ :project,
+ { fullPath: project.full_path },
+ query_graphql_field(
+ :commitReferences,
+ { commitSha: commit_sha },
+ query_graphql_field(:tippingTags, args, :names)
+ )
+ )
+ end
+
+ context 'with authorized user' do
+ it 'returns tags names tipping the commit' do
+ post_query
+
+ expect(data).to eq([tag_name])
+ end
+ end
+
+ include_context 'with the limit argument'
+ end
+
+ context 'with path Query.project(fullPath).commitReferences(commitSha).tippingBranches' do
+ let(:path) { %w[project commitReferences tippingBranches names] }
+
+ let(:query) do
+ graphql_query_for(
+ :project,
+ { fullPath: project.full_path },
+ query_graphql_field(
+ :commitReferences,
+ { commitSha: commit_sha },
+ query_graphql_field(:tippingBranches, args, :names)
+ )
+ )
+ end
+
+ it 'returns branches names tipping the commit' do
+ post_query
+
+ expect(data).to eq(branches_names)
+ end
+
+ include_context 'with the limit argument'
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/project/project_statistics_redirect_spec.rb b/spec/requests/api/graphql/project/project_statistics_redirect_spec.rb
new file mode 100644
index 00000000000..8049a75ace3
--- /dev/null
+++ b/spec/requests/api/graphql/project/project_statistics_redirect_spec.rb
@@ -0,0 +1,78 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'rendering project storage type routes', feature_category: :shared do
+ include GraphqlHelpers
+
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:user) { create(:user) }
+
+ let(:query) do
+ graphql_query_for('project',
+ { 'fullPath' => project.full_path },
+ "statisticsDetailsPaths { #{all_graphql_fields_for('ProjectStatisticsRedirect')} }")
+ end
+
+ it_behaves_like 'a working graphql query' do
+ before do
+ post_graphql(query, current_user: user)
+ end
+ end
+
+ shared_examples 'valid routes for storage type' do
+ it 'contains all keys' do
+ post_graphql(query, current_user: user)
+
+ expect(graphql_data['project']['statisticsDetailsPaths'].keys).to match_array(
+ %w[repository buildArtifacts wiki packages snippets containerRegistry]
+ )
+ end
+
+ it 'contains valid paths' do
+ repository_url = Gitlab::Routing.url_helpers.project_tree_url(project, "master")
+ wiki_url = Gitlab::Routing.url_helpers.project_wikis_pages_url(project)
+ build_artifacts_url = Gitlab::Routing.url_helpers.project_artifacts_url(project)
+ packages_url = Gitlab::Routing.url_helpers.project_packages_url(project)
+ snippets_url = Gitlab::Routing.url_helpers.project_snippets_url(project)
+ container_registry_url = Gitlab::Routing.url_helpers.project_container_registry_index_url(project)
+
+ post_graphql(query, current_user: user)
+
+ expect(graphql_data['project']['statisticsDetailsPaths'].values).to match_array [repository_url,
+ wiki_url,
+ build_artifacts_url,
+ packages_url,
+ snippets_url,
+ container_registry_url]
+ end
+ end
+
+ context 'when project is public' do
+ it_behaves_like 'valid routes for storage type'
+
+ context 'when user is nil' do
+ let_it_be(:user) { nil }
+
+ it_behaves_like 'valid routes for storage type'
+ end
+ end
+
+ context 'when project is private' do
+ let_it_be(:project) { create(:project, :private) }
+
+ before do
+ project.add_reporter(user)
+ end
+
+ it_behaves_like 'valid routes for storage type'
+
+ context 'when user is nil' do
+ it 'hides statisticsDetailsPaths for nil users' do
+ post_graphql(query, current_user: nil)
+
+ expect(graphql_data['project']).to be_blank
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/project/tags_tipping_at_commit_spec.rb b/spec/requests/api/graphql/project/tags_tipping_at_commit_spec.rb
deleted file mode 100644
index a5e26482a9e..00000000000
--- a/spec/requests/api/graphql/project/tags_tipping_at_commit_spec.rb
+++ /dev/null
@@ -1,67 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'Query.project(fullPath).tagsTippingAtCommit(commitSha)', feature_category: :source_code_management do
- include GraphqlHelpers
- include Presentable
-
- let_it_be(:project) { create(:project, :repository) }
- let_it_be(:repository) { project.repository.raw }
- let_it_be(:current_user) { project.first_owner }
- let_it_be(:tag_name) { 'v1.0.0' }
-
- let(:post_query) { post_graphql(query, current_user: current_user) }
- let(:path) { %w[project tagsTippingAtCommit names] }
- let(:data) { graphql_data.dig(*path) }
-
- let(:query) do
- graphql_query_for(
- :project,
- { fullPath: project.full_path },
- query_graphql_field(:tagsTippingAtCommit, { commitSha: commit_sha }, :names)
- )
- end
-
- context 'when commit exists and is tipping tags' do
- let(:commit_sha) { repository.find_tag(tag_name).dereferenced_target.sha }
-
- context 'with authorized user' do
- it 'returns tags names tipping the commit' do
- post_query
-
- expect(data).to eq([tag_name])
- end
- end
-
- context 'when user is not authorized' do
- let(:current_user) { create(:user) }
-
- it 'returns tags names tipping the commit' do
- post_query
-
- expect(data).to eq(nil)
- end
- end
- end
-
- context 'when commit does not exist' do
- let(:commit_sha) { '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff4' }
-
- it 'returns tags names tipping the commit' do
- post_query
-
- expect(data).to eq([])
- end
- end
-
- context 'when commit exists but does not tip any tags' do
- let(:commit_sha) { project.repository.commits(nil, { limit: 4 }).commits[2].id }
-
- it 'returns tags names tipping the commit' do
- post_query
-
- expect(data).to eq([])
- end
- end
-end
diff --git a/spec/requests/api/metrics/dashboard/annotations_spec.rb b/spec/requests/api/metrics/dashboard/annotations_spec.rb
index cefd5896158..250fe2a3ee3 100644
--- a/spec/requests/api/metrics/dashboard/annotations_spec.rb
+++ b/spec/requests/api/metrics/dashboard/annotations_spec.rb
@@ -16,6 +16,7 @@ RSpec.describe API::Metrics::Dashboard::Annotations, feature_category: :metrics
let(:url) { "/#{source_type.pluralize}/#{source.id}/metrics_dashboard/annotations" }
before do
+ stub_feature_flags(remove_monitor_metrics: false)
project.add_developer(user)
end
@@ -104,6 +105,18 @@ RSpec.describe API::Metrics::Dashboard::Annotations, feature_category: :metrics
expect(response).to have_gitlab_http_status(:forbidden)
end
end
+
+ context 'when metrics dashboard feature is unavailable' do
+ before do
+ stub_feature_flags(remove_monitor_metrics: true)
+ end
+
+ it 'returns 404 not found' do
+ post api(url, user), params: params
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
end
end
diff --git a/spec/requests/api/project_packages_spec.rb b/spec/requests/api/project_packages_spec.rb
index 69579323908..c003ae9cd48 100644
--- a/spec/requests/api/project_packages_spec.rb
+++ b/spec/requests/api/project_packages_spec.rb
@@ -224,19 +224,15 @@ RSpec.describe API::ProjectPackages, feature_category: :package_registry do
context 'without the need for a license' do
context 'with build info' do
- let_it_be(:package1) { create(:npm_package, :with_build, project: project) }
-
- it 'returns an empty array for the pipelines attribute' do
- subject
-
- expect(json_response['pipelines']).to be_empty
- end
-
it 'does not result in additional queries' do
control = ActiveRecord::QueryRecorder.new do
get api(package_url, user)
end
+ pipeline = create(:ci_pipeline, user: user, project: project)
+ create(:ci_build, user: user, pipeline: pipeline, project: project)
+ create(:package_build_info, package: package1, pipeline: pipeline)
+
expect do
get api(package_url, user)
end.not_to exceed_query_limit(control)
diff --git a/spec/requests/api/project_templates_spec.rb b/spec/requests/api/project_templates_spec.rb
index 38d6a05a104..91e5ed76c37 100644
--- a/spec/requests/api/project_templates_spec.rb
+++ b/spec/requests/api/project_templates_spec.rb
@@ -10,6 +10,7 @@ RSpec.describe API::ProjectTemplates, feature_category: :source_code_management
let(:url_encoded_path) { "#{public_project.namespace.path}%2F#{public_project.path}" }
before do
+ stub_feature_flags(remove_monitor_metrics: false)
private_project.add_developer(developer)
end
@@ -71,6 +72,18 @@ RSpec.describe API::ProjectTemplates, feature_category: :source_code_management
expect(json_response).to satisfy_one { |template| template['key'] == 'Default' }
end
+ context 'when metrics dashboard feature is unavailable' do
+ before do
+ stub_feature_flags(remove_monitor_metrics: true)
+ end
+
+ it 'returns 400 bad request like other unknown types' do
+ get api("/projects/#{public_project.id}/templates/metrics_dashboard_ymls")
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+ end
+
it 'returns issue templates' do
get api("/projects/#{private_project.id}/templates/issues", developer)
@@ -171,6 +184,18 @@ RSpec.describe API::ProjectTemplates, feature_category: :source_code_management
expect(json_response['name']).to eq('Default')
end
+ context 'when metrics dashboard feature is unavailable' do
+ before do
+ stub_feature_flags(remove_monitor_metrics: true)
+ end
+
+ it 'returns 400 bad request like other unknown types' do
+ get api("/projects/#{public_project.id}/templates/metrics_dashboard_ymls/Default")
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+ end
+
it 'returns a specific license' do
get api("/projects/#{public_project.id}/templates/licenses/mit")
diff --git a/spec/services/jira_connect/sync_service_spec.rb b/spec/services/jira_connect/sync_service_spec.rb
index fc1b4e997a5..7457cdca13c 100644
--- a/spec/services/jira_connect/sync_service_spec.rb
+++ b/spec/services/jira_connect/sync_service_spec.rb
@@ -44,16 +44,18 @@ RSpec.describe JiraConnect::SyncService, feature_category: :integrations do
subject
end
- context 'when a request returns an error' do
- it 'logs the response as an error' do
+ context 'when a request returns errors' do
+ it 'logs each response as an error' do
expect_next(client).to store_info(
[
{ 'errorMessages' => ['some error message'] },
- { 'errorMessages' => ['x'] }
+ { 'errorMessage' => 'a single error message' },
+ { 'errorMessages' => [] },
+ { 'errorMessage' => '' }
])
expect_log(:error, { 'errorMessages' => ['some error message'] })
- expect_log(:error, { 'errorMessages' => ['x'] })
+ expect_log(:error, { 'errorMessage' => 'a single error message' })
subject
end
diff --git a/spec/support/import_export/export_file_helper.rb b/spec/support/import_export/export_file_helper.rb
index 9a26f50903f..ee1b4a3c33a 100644
--- a/spec/support/import_export/export_file_helper.rb
+++ b/spec/support/import_export/export_file_helper.rb
@@ -21,21 +21,25 @@ module ExportFileHelper
create(:label_link, label: label, target: issue)
- ci_pipeline = create(:ci_pipeline,
- project: project,
- sha: merge_request.diff_head_sha,
- ref: merge_request.source_branch,
- statuses: [commit_status])
+ ci_pipeline = create(
+ :ci_pipeline,
+ project: project,
+ sha: merge_request.diff_head_sha,
+ ref: merge_request.source_branch,
+ statuses: [commit_status]
+ )
create(:ci_build, pipeline: ci_pipeline, project: project)
create(:milestone, project: project)
create(:note, noteable: issue, project: project)
create(:note, noteable: merge_request, project: project)
create(:note, noteable: snippet, project: project)
- create(:note_on_commit,
- author: user,
- project: project,
- commit_id: ci_pipeline.sha)
+ create(
+ :note_on_commit,
+ author: user,
+ project: project,
+ commit_id: ci_pipeline.sha
+ )
event = create(:event, :created, target: milestone, project: project, author: user, action: 5)
create(:push_event_payload, event: event)
diff --git a/spec/support/shared_examples/controllers/snippets_sort_order_shared_examples.rb b/spec/support/shared_examples/controllers/snippets_sort_order_shared_examples.rb
index 112b9cbb204..f658cfac0f5 100644
--- a/spec/support/shared_examples/controllers/snippets_sort_order_shared_examples.rb
+++ b/spec/support/shared_examples/controllers/snippets_sort_order_shared_examples.rb
@@ -15,8 +15,9 @@ RSpec.shared_examples 'snippets sort order' do
context 'when no sort param is provided' do
it 'calls SnippetsFinder with updated_at sort option' do
- expect(SnippetsFinder).to receive(:new).with(user,
- hash_including(sort: 'updated_desc')).and_call_original
+ expect(SnippetsFinder).to receive(:new)
+ .with(user, hash_including(sort: 'updated_desc'))
+ .and_call_original
subject
end
@@ -27,8 +28,9 @@ RSpec.shared_examples 'snippets sort order' do
let(:sort_argument) { { sort: order } }
it 'calls SnippetsFinder with the given sort param' do
- expect(SnippetsFinder).to receive(:new).with(user,
- hash_including(sort: order)).and_call_original
+ expect(SnippetsFinder).to receive(:new)
+ .with(user, hash_including(sort: order))
+ .and_call_original
subject
end
diff --git a/spec/support/shared_examples/controllers/wiki_actions_shared_examples.rb b/spec/support/shared_examples/controllers/wiki_actions_shared_examples.rb
index 768b54dc73e..32aa566c27e 100644
--- a/spec/support/shared_examples/controllers/wiki_actions_shared_examples.rb
+++ b/spec/support/shared_examples/controllers/wiki_actions_shared_examples.rb
@@ -399,11 +399,10 @@ RSpec.shared_examples 'wiki controller actions' do
let(:id_param) { wiki_title }
subject(:request) do
- patch(:update,
- params: routing_params.merge(
- id: id_param,
- wiki: { title: new_title, content: new_content }
- ))
+ patch(:update, params: routing_params.merge(
+ id: id_param,
+ wiki: { title: new_title, content: new_content }
+ ))
end
it_behaves_like 'edit action'
@@ -439,10 +438,9 @@ RSpec.shared_examples 'wiki controller actions' do
let(:new_content) { 'New content' }
subject(:request) do
- post(:create,
- params: routing_params.merge(
- wiki: { title: new_title, content: new_content }
- ))
+ post(:create, params: routing_params.merge(
+ wiki: { title: new_title, content: new_content }
+ ))
end
context 'when page is valid' do
@@ -476,10 +474,9 @@ RSpec.shared_examples 'wiki controller actions' do
let(:delete_user) { user }
subject(:request) do
- delete(:destroy,
- params: routing_params.merge(
- id: id_param
- ))
+ delete(:destroy, params: routing_params.merge(
+ id: id_param
+ ))
end
before do
diff --git a/spec/support/shared_examples/features/editable_merge_request_shared_examples.rb b/spec/support/shared_examples/features/editable_merge_request_shared_examples.rb
index 2bcbd5e5190..14e53dc8655 100644
--- a/spec/support/shared_examples/features/editable_merge_request_shared_examples.rb
+++ b/spec/support/shared_examples/features/editable_merge_request_shared_examples.rb
@@ -83,9 +83,15 @@ RSpec.shared_examples 'an editable merge request' do
fill_in 'merge_request_title', with: 'bug 345'
fill_in 'merge_request_description', with: 'bug description'
- click_button 'Save changes'
-
- expect(page).to have_content 'Someone edited the merge request the same time you did'
+ click_button _('Save changes')
+
+ expect(page).to have_content(
+ format(
+ _("Someone edited this %{model_name} at the same time you did. Please check out the %{link_to_model} and make sure your changes will not unintentionally remove theirs."), # rubocop:disable Layout/LineLength
+ model_name: _('merge request'),
+ link_to_model: _('merge request')
+ )
+ )
end
it 'preserves description textarea height', :js do
diff --git a/spec/support/shared_examples/features/milestone_editing_shared_examples.rb b/spec/support/shared_examples/features/milestone_editing_shared_examples.rb
new file mode 100644
index 00000000000..d21bf62ecfa
--- /dev/null
+++ b/spec/support/shared_examples/features/milestone_editing_shared_examples.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'milestone handling version conflicts' do
+ it 'warns about version conflict when milestone has been updated in the background' do
+ # Update the milestone in the background in order to trigger a version conflict
+ milestone.update!(title: "New title")
+
+ fill_in _('Title'), with: 'Title for version conflict'
+ fill_in _('Description'), with: 'Description for version conflict'
+
+ click_button _('Save changes')
+
+ expect(page).to have_content(
+ format(
+ _("Someone edited this %{model_name} at the same time you did. Please check out the %{link_to_model} and make sure your changes will not unintentionally remove theirs."), # rubocop:disable Layout/LineLength
+ model_name: _('milestone'),
+ link_to_model: _('milestone')
+ )
+ )
+ end
+end
diff --git a/spec/support/shared_examples/features/search/redacted_search_results_shared_examples.rb b/spec/support/shared_examples/features/search/redacted_search_results_shared_examples.rb
index 4d242d0e719..cbd0ffbab21 100644
--- a/spec/support/shared_examples/features/search/redacted_search_results_shared_examples.rb
+++ b/spec/support/shared_examples/features/search/redacted_search_results_shared_examples.rb
@@ -48,14 +48,18 @@ RSpec.shared_examples 'a redacted search results' do
it 'redacts the inaccessible issue' do
expect(search_service.send(:logger))
.to receive(:error)
- .with(hash_including(
- message: "redacted_search_results",
- current_user_id: user.id,
- query: search,
- filtered: array_including(
- [
- { class_name: 'Issue', id: unreadable.id, ability: :read_issue }
- ])))
+ .with(
+ hash_including(
+ message: "redacted_search_results",
+ current_user_id: user.id,
+ query: search,
+ filtered: array_including(
+ [
+ { class_name: 'Issue', id: unreadable.id, ability: :read_issue }
+ ]
+ )
+ )
+ )
expect(result).to contain_exactly(readable)
end
@@ -95,16 +99,18 @@ RSpec.shared_examples 'a redacted search results' do
end
let(:unredacted_results) do
- ar_relation(Note,
- readable_note_on_commit,
- readable_diff_note,
- readable_note_on_mr,
- readable_diff_note_on_mr,
- readable_note_on_project_snippet,
- unreadable_note_on_commit,
- unreadable_diff_note,
- unreadable_note_on_mr,
- unreadable_note_on_project_snippet)
+ ar_relation(
+ Note,
+ readable_note_on_commit,
+ readable_diff_note,
+ readable_note_on_mr,
+ readable_diff_note_on_mr,
+ readable_note_on_project_snippet,
+ unreadable_note_on_commit,
+ unreadable_diff_note,
+ unreadable_note_on_mr,
+ unreadable_note_on_project_snippet
+ )
end
let(:scope) { 'notes' }
@@ -112,23 +118,29 @@ RSpec.shared_examples 'a redacted search results' do
it 'redacts the inaccessible notes' do
expect(search_service.send(:logger))
.to receive(:error)
- .with(hash_including(
- message: "redacted_search_results",
- current_user_id: user.id,
- query: search,
- filtered: array_including(
- [
- { class_name: 'Note', id: unreadable_note_on_commit.id, ability: :read_note },
- { class_name: 'DiffNote', id: unreadable_diff_note.id, ability: :read_note },
- { class_name: 'DiscussionNote', id: unreadable_note_on_mr.id, ability: :read_note },
- { class_name: 'Note', id: unreadable_note_on_project_snippet.id, ability: :read_note }
- ])))
-
- expect(result).to contain_exactly(readable_note_on_commit,
- readable_diff_note,
- readable_note_on_mr,
- readable_diff_note_on_mr,
- readable_note_on_project_snippet)
+ .with(
+ hash_including(
+ message: "redacted_search_results",
+ current_user_id: user.id,
+ query: search,
+ filtered: array_including(
+ [
+ { class_name: 'Note', id: unreadable_note_on_commit.id, ability: :read_note },
+ { class_name: 'DiffNote', id: unreadable_diff_note.id, ability: :read_note },
+ { class_name: 'DiscussionNote', id: unreadable_note_on_mr.id, ability: :read_note },
+ { class_name: 'Note', id: unreadable_note_on_project_snippet.id, ability: :read_note }
+ ]
+ )
+ )
+ )
+
+ expect(result).to contain_exactly(
+ readable_note_on_commit,
+ readable_diff_note,
+ readable_note_on_mr,
+ readable_diff_note_on_mr,
+ readable_note_on_project_snippet
+ )
end
end
@@ -141,14 +153,18 @@ RSpec.shared_examples 'a redacted search results' do
it 'redacts the inaccessible merge request' do
expect(search_service.send(:logger))
.to receive(:error)
- .with(hash_including(
- message: "redacted_search_results",
- current_user_id: user.id,
- query: search,
- filtered: array_including(
- [
- { class_name: 'MergeRequest', id: unreadable.id, ability: :read_merge_request }
- ])))
+ .with(
+ hash_including(
+ message: "redacted_search_results",
+ current_user_id: user.id,
+ query: search,
+ filtered: array_including(
+ [
+ { class_name: 'MergeRequest', id: unreadable.id, ability: :read_merge_request }
+ ]
+ )
+ )
+ )
expect(result).to contain_exactly(readable)
end
@@ -169,14 +185,18 @@ RSpec.shared_examples 'a redacted search results' do
it 'redacts the inaccessible blob' do
expect(search_service.send(:logger))
.to receive(:error)
- .with(hash_including(
- message: "redacted_search_results",
- current_user_id: user.id,
- query: search,
- filtered: array_including(
- [
- { class_name: 'Gitlab::Search::FoundBlob', id: unreadable.id, ability: :read_blob }
- ])))
+ .with(
+ hash_including(
+ message: "redacted_search_results",
+ current_user_id: user.id,
+ query: search,
+ filtered: array_including(
+ [
+ { class_name: 'Gitlab::Search::FoundBlob', id: unreadable.id, ability: :read_blob }
+ ]
+ )
+ )
+ )
expect(result).to contain_exactly(readable)
end
@@ -191,14 +211,18 @@ RSpec.shared_examples 'a redacted search results' do
it 'redacts the inaccessible blob' do
expect(search_service.send(:logger))
.to receive(:error)
- .with(hash_including(
- message: "redacted_search_results",
- current_user_id: user.id,
- query: search,
- filtered: array_including(
- [
- { class_name: 'Gitlab::Search::FoundWikiPage', id: unreadable.id, ability: :read_wiki_page }
- ])))
+ .with(
+ hash_including(
+ message: "redacted_search_results",
+ current_user_id: user.id,
+ query: search,
+ filtered: array_including(
+ [
+ { class_name: 'Gitlab::Search::FoundWikiPage', id: unreadable.id, ability: :read_wiki_page }
+ ]
+ )
+ )
+ )
expect(result).to contain_exactly(readable)
end
@@ -213,14 +237,18 @@ RSpec.shared_examples 'a redacted search results' do
it 'redacts the inaccessible snippet' do
expect(search_service.send(:logger))
.to receive(:error)
- .with(hash_including(
- message: "redacted_search_results",
- current_user_id: user.id,
- query: search,
- filtered: array_including(
- [
- { class_name: 'ProjectSnippet', id: unreadable.id, ability: :read_snippet }
- ])))
+ .with(
+ hash_including(
+ message: "redacted_search_results",
+ current_user_id: user.id,
+ query: search,
+ filtered: array_including(
+ [
+ { class_name: 'ProjectSnippet', id: unreadable.id, ability: :read_snippet }
+ ]
+ )
+ )
+ )
expect(result).to contain_exactly(readable)
end
@@ -239,14 +267,18 @@ RSpec.shared_examples 'a redacted search results' do
it 'redacts the inaccessible snippet' do
expect(search_service.send(:logger))
.to receive(:error)
- .with(hash_including(
- message: "redacted_search_results",
- current_user_id: user.id,
- query: search,
- filtered: array_including(
- [
- { class_name: 'PersonalSnippet', id: unreadable.id, ability: :read_snippet }
- ])))
+ .with(
+ hash_including(
+ message: "redacted_search_results",
+ current_user_id: user.id,
+ query: search,
+ filtered: array_including(
+ [
+ { class_name: 'PersonalSnippet', id: unreadable.id, ability: :read_snippet }
+ ]
+ )
+ )
+ )
expect(result).to contain_exactly(readable)
end
@@ -265,14 +297,18 @@ RSpec.shared_examples 'a redacted search results' do
it 'redacts the inaccessible commit' do
expect(search_service.send(:logger))
.to receive(:error)
- .with(hash_including(
- message: "redacted_search_results",
- current_user_id: user.id,
- query: search,
- filtered: array_including(
- [
- { class_name: 'Commit', id: unreadable.id, ability: :read_commit }
- ])))
+ .with(
+ hash_including(
+ message: "redacted_search_results",
+ current_user_id: user.id,
+ query: search,
+ filtered: array_including(
+ [
+ { class_name: 'Commit', id: unreadable.id, ability: :read_commit }
+ ]
+ )
+ )
+ )
expect(result).to contain_exactly(readable)
end
diff --git a/spec/support/shared_examples/features/wiki/user_views_wiki_page_shared_examples.rb b/spec/support/shared_examples/features/wiki/user_views_wiki_page_shared_examples.rb
index a7c32932ba7..767caffd417 100644
--- a/spec/support/shared_examples/features/wiki/user_views_wiki_page_shared_examples.rb
+++ b/spec/support/shared_examples/features/wiki/user_views_wiki_page_shared_examples.rb
@@ -9,9 +9,11 @@ RSpec.shared_examples 'User views a wiki page' do
let(:path) { 'image.png' }
let(:wiki_page) do
- create(:wiki_page,
- wiki: wiki,
- title: 'home', content: "Look at this [image](#{path})\n\n ![alt text](#{path})")
+ create(
+ :wiki_page,
+ wiki: wiki,
+ title: 'home', content: "Look at this [image](#{path})\n\n ![alt text](#{path})"
+ )
end
before do
diff --git a/spec/support/shared_examples/graphql/members_shared_examples.rb b/spec/support/shared_examples/graphql/members_shared_examples.rb
index 5cba8baa829..5ab17f5a49d 100644
--- a/spec/support/shared_examples/graphql/members_shared_examples.rb
+++ b/spec/support/shared_examples/graphql/members_shared_examples.rb
@@ -39,8 +39,10 @@ RSpec.shared_examples 'querying members with a group' do
let(:base_args) { { relations: described_class.arguments['relations'].default_value } }
subject do
- resolve(described_class, obj: resource, args: base_args.merge(args),
- ctx: { current_user: user_4 }, arg_style: :internal)
+ resolve(
+ described_class, obj: resource, args: base_args.merge(args),
+ ctx: { current_user: user_4 }, arg_style: :internal
+ )
end
describe '#resolve' do
@@ -83,8 +85,10 @@ RSpec.shared_examples 'querying members with a group' do
let_it_be(:other_user) { create(:user) }
subject do
- resolve(described_class, obj: resource, args: base_args.merge(args),
- ctx: { current_user: other_user }, arg_style: :internal)
+ resolve(
+ described_class, obj: resource, args: base_args.merge(args),
+ ctx: { current_user: other_user }, arg_style: :internal
+ )
end
it 'generates an error' do
diff --git a/spec/support/shared_examples/graphql/mutation_shared_examples.rb b/spec/support/shared_examples/graphql/mutation_shared_examples.rb
index dc590e23ace..808fb097f29 100644
--- a/spec/support/shared_examples/graphql/mutation_shared_examples.rb
+++ b/spec/support/shared_examples/graphql/mutation_shared_examples.rb
@@ -15,7 +15,7 @@ RSpec.shared_examples 'a mutation that returns top-level errors' do |errors: []|
expect(graphql_errors).to be_present
- error_messages = graphql_errors.map { |e| e['message'] }
+ error_messages = graphql_errors.pluck('message')
expect(error_messages).to match_errors
end
@@ -25,7 +25,7 @@ end
# the mutation.
RSpec.shared_examples 'a mutation that returns a top-level access error' do
include_examples 'a mutation that returns top-level errors',
- errors: [Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR]
+ errors: [Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR]
end
RSpec.shared_examples 'an invalid argument to the mutation' do |argument_name:|
diff --git a/spec/support/shared_examples/graphql/mutations/set_assignees_shared_examples.rb b/spec/support/shared_examples/graphql/mutations/set_assignees_shared_examples.rb
index 022e2308517..3b9dadf2e80 100644
--- a/spec/support/shared_examples/graphql/mutations/set_assignees_shared_examples.rb
+++ b/spec/support/shared_examples/graphql/mutations/set_assignees_shared_examples.rb
@@ -16,10 +16,12 @@ RSpec.shared_examples 'an assignable resource' do
let(:mode) { described_class.arguments['operationMode'].default_value }
subject do
- mutation.resolve(project_path: resource.project.full_path,
- iid: resource.iid,
- operation_mode: mode,
- assignee_usernames: assignee_usernames)
+ mutation.resolve(
+ project_path: resource.project.full_path,
+ iid: resource.iid,
+ operation_mode: mode,
+ assignee_usernames: assignee_usernames
+ )
end
it 'raises an error if the resource is not accessible to the user' do
diff --git a/spec/support/shared_examples/graphql/notes_on_noteables_shared_examples.rb b/spec/support/shared_examples/graphql/notes_on_noteables_shared_examples.rb
index 09239ced73a..99d122e8254 100644
--- a/spec/support/shared_examples/graphql/notes_on_noteables_shared_examples.rb
+++ b/spec/support/shared_examples/graphql/notes_on_noteables_shared_examples.rb
@@ -4,9 +4,11 @@ RSpec.shared_context 'exposing regular notes on a noteable in GraphQL' do
include GraphqlHelpers
let(:note) do
- create(:note,
- noteable: noteable,
- project: (noteable.project if noteable.respond_to?(:project)))
+ create(
+ :note,
+ noteable: noteable,
+ project: (noteable.project if noteable.respond_to?(:project))
+ )
end
let(:user) { note.author }
diff --git a/spec/support/shared_examples/requests/api/container_repositories_shared_examples.rb b/spec/support/shared_examples/requests/api/container_repositories_shared_examples.rb
index f5c41416763..3ff52166990 100644
--- a/spec/support/shared_examples/requests/api/container_repositories_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/container_repositories_shared_examples.rb
@@ -18,7 +18,7 @@ RSpec.shared_examples 'returns repositories for allowed users' do |user_type, sc
subject
expect(json_response.length).to eq(2)
- expect(json_response.map { |repository| repository['id'] }).to contain_exactly(
+ expect(json_response.pluck('id')).to contain_exactly(
root_repository.id, test_repository.id)
expect(response.body).not_to include('tags')
expect(response.body).not_to include('tags_count')
@@ -47,7 +47,7 @@ RSpec.shared_examples 'returns tags for allowed users' do |user_type, scope|
subject
expect(json_response.length).to eq(2)
- expect(json_response.map { |repository| repository['id'] }).to contain_exactly(
+ expect(json_response.pluck('id')).to contain_exactly(
root_repository.id, test_repository.id)
expect(response.body).to include('tags')
end
diff --git a/spec/support/shared_examples/requests/api/custom_attributes_shared_examples.rb b/spec/support/shared_examples/requests/api/custom_attributes_shared_examples.rb
index e3ba51addaf..804221b7416 100644
--- a/spec/support/shared_examples/requests/api/custom_attributes_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/custom_attributes_shared_examples.rb
@@ -14,7 +14,7 @@ RSpec.shared_examples 'custom attributes endpoints' do |attributable_name|
get api("/#{attributable_name}", user), params: { custom_attributes: { foo: 'foo', bar: 'bar' } }
expect(response).to have_gitlab_http_status(:ok)
- expect(json_response.map { |r| r['id'] }).to include(attributable.id, other_attributable.id)
+ expect(json_response.pluck('id')).to include(attributable.id, other_attributable.id)
end
end
diff --git a/spec/support/shared_examples/requests/api/graphql/packages/group_and_project_packages_list_shared_examples.rb b/spec/support/shared_examples/requests/api/graphql/packages/group_and_project_packages_list_shared_examples.rb
index f5835460a77..5e9dfc826d4 100644
--- a/spec/support/shared_examples/requests/api/graphql/packages/group_and_project_packages_list_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/graphql/packages/group_and_project_packages_list_shared_examples.rb
@@ -279,11 +279,11 @@ RSpec.shared_examples 'group and project packages query' do
end
def npm_pipeline_ids
- graphql_data_npm_package.dig('pipelines', 'nodes').map { |pipeline| pipeline['id'] }
+ graphql_data_npm_package.dig('pipelines', 'nodes').pluck('id')
end
def composer_pipeline_ids
- graphql_data_composer_package.dig('pipelines', 'nodes').map { |pipeline| pipeline['id'] }
+ graphql_data_composer_package.dig('pipelines', 'nodes').pluck('id')
end
def graphql_data_npm_package
diff --git a/spec/support/shared_examples/requests/api/graphql/packages/package_details_shared_examples.rb b/spec/support/shared_examples/requests/api/graphql/packages/package_details_shared_examples.rb
index b4019d7c232..161f4a02b8c 100644
--- a/spec/support/shared_examples/requests/api/graphql/packages/package_details_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/graphql/packages/package_details_shared_examples.rb
@@ -38,7 +38,7 @@ RSpec.shared_examples 'a package with files' do
context 'with package files pending destruction' do
let_it_be(:package_file_pending_destruction) { create(:package_file, :pending_destruction, package: package) }
- let(:response_package_file_ids) { package_files_response.map { |pf| pf['id'] } }
+ let(:response_package_file_ids) { package_files_response.pluck('id') }
it 'does not return them' do
expect(package.reload.package_files).to include(package_file_pending_destruction)
diff --git a/spec/support/shared_examples/requests/api/labels_api_shared_examples.rb b/spec/support/shared_examples/requests/api/labels_api_shared_examples.rb
index 41d21490343..fba0533251a 100644
--- a/spec/support/shared_examples/requests/api/labels_api_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/labels_api_shared_examples.rb
@@ -9,6 +9,6 @@ RSpec.shared_examples 'fetches labels' do
expect(json_response).to be_an Array
expect(json_response).to all(match_schema('public_api/v4/labels/label'))
expect(json_response.size).to eq(expected_labels.size)
- expect(json_response.map { |r| r['name'] }).to match_array(expected_labels)
+ expect(json_response.pluck('name')).to match_array(expected_labels)
end
end
diff --git a/spec/support/shared_examples/requests/api/milestones_shared_examples.rb b/spec/support/shared_examples/requests/api/milestones_shared_examples.rb
index 1ea11ba3d7c..ee7d0e86771 100644
--- a/spec/support/shared_examples/requests/api/milestones_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/milestones_shared_examples.rb
@@ -52,7 +52,7 @@ RSpec.shared_examples 'group and project milestones' do |route_definition|
expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to be_an Array
expect(json_response.length).to eq(2)
- expect(json_response.map { |m| m['id'] }).to match_array([closed_milestone.id, other_milestone.id])
+ expect(json_response.pluck('id')).to match_array([closed_milestone.id, other_milestone.id])
end
it 'does not return any milestone if none found' do
@@ -293,7 +293,7 @@ RSpec.shared_examples 'group and project milestones' do |route_definition|
expect(json_response).to be_an Array
# 2 for projects, 3 for group(which has another project with an issue)
expect(json_response.size).to be_between(2, 3)
- expect(json_response.map { |issue| issue['id'] }).to include(issue.id, confidential_issue.id)
+ expect(json_response.pluck('id')).to include(issue.id, confidential_issue.id)
end
it 'does not return confidential issues to team members with guest role' do
@@ -306,7 +306,7 @@ RSpec.shared_examples 'group and project milestones' do |route_definition|
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
expect(json_response.size).to eq(1)
- expect(json_response.map { |issue| issue['id'] }).to include(issue.id)
+ expect(json_response.pluck('id')).to include(issue.id)
end
it 'does not return confidential issues to regular users' do
@@ -316,7 +316,7 @@ RSpec.shared_examples 'group and project milestones' do |route_definition|
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
expect(json_response.size).to eq(1)
- expect(json_response.map { |issue| issue['id'] }).to include(issue.id)
+ expect(json_response.pluck('id')).to include(issue.id)
end
it 'returns issues ordered by label priority' do
diff --git a/spec/support/shared_examples/requests/api/notes_shared_examples.rb b/spec/support/shared_examples/requests/api/notes_shared_examples.rb
index 0518749452e..b44ff952cdf 100644
--- a/spec/support/shared_examples/requests/api/notes_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/notes_shared_examples.rb
@@ -14,7 +14,7 @@ RSpec.shared_examples 'noteable API' do |parent_type, noteable_type, id_name|
it 'sorts by created_at in descending order by default' do
get api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/notes", user, admin_mode: user.admin?)
- response_dates = json_response.map { |note| note['created_at'] }
+ response_dates = json_response.pluck('created_at')
expect(json_response.length).to eq(4)
expect(response_dates).to eq(response_dates.sort.reverse)
@@ -42,7 +42,7 @@ RSpec.shared_examples 'noteable API' do |parent_type, noteable_type, id_name|
it 'page breaks first page correctly' do
get api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/notes?per_page=4", user, admin_mode: user.admin?)
- response_ids = json_response.map { |note| note['id'] }
+ response_ids = json_response.pluck('id')
expect(response_ids).to include(@note2.id)
expect(response_ids).not_to include(@first_note.id)
@@ -51,7 +51,7 @@ RSpec.shared_examples 'noteable API' do |parent_type, noteable_type, id_name|
it 'page breaks second page correctly' do
get api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/notes?per_page=4&page=2", user, admin_mode: user.admin?)
- response_ids = json_response.map { |note| note['id'] }
+ response_ids = json_response.pluck('id')
expect(response_ids).not_to include(@note2.id)
expect(response_ids).to include(@first_note.id)
@@ -62,7 +62,7 @@ RSpec.shared_examples 'noteable API' do |parent_type, noteable_type, id_name|
it 'sorts by ascending order when requested' do
get api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/notes?sort=asc", user, admin_mode: user.admin?)
- response_dates = json_response.map { |note| note['created_at'] }
+ response_dates = json_response.pluck('created_at')
expect(json_response.length).to eq(4)
expect(response_dates).to eq(response_dates.sort)
@@ -71,7 +71,7 @@ RSpec.shared_examples 'noteable API' do |parent_type, noteable_type, id_name|
it 'sorts by updated_at in descending order when requested' do
get api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/notes?order_by=updated_at", user, admin_mode: user.admin?)
- response_dates = json_response.map { |note| note['updated_at'] }
+ response_dates = json_response.pluck('updated_at')
expect(json_response.length).to eq(4)
expect(response_dates).to eq(response_dates.sort.reverse)
@@ -80,7 +80,7 @@ RSpec.shared_examples 'noteable API' do |parent_type, noteable_type, id_name|
it 'sorts by updated_at in ascending order when requested' do
get api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/notes?order_by=updated_at&sort=asc", user, admin_mode: user.admin?)
- response_dates = json_response.map { |note| note['updated_at'] }
+ response_dates = json_response.pluck('updated_at')
expect(json_response.length).to eq(4)
expect(response_dates).to eq(response_dates.sort)
diff --git a/spec/support/shared_examples/requests/api/repository_storage_moves_shared_examples.rb b/spec/support/shared_examples/requests/api/repository_storage_moves_shared_examples.rb
index 7df8d6a513d..3913d29e086 100644
--- a/spec/support/shared_examples/requests/api/repository_storage_moves_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/repository_storage_moves_shared_examples.rb
@@ -70,7 +70,7 @@ RSpec.shared_examples 'repository_storage_moves API' do |container_type|
get_container_repository_storage_moves
- json_ids = json_response.map { |storage_move| storage_move['id'] }
+ json_ids = json_response.pluck('id')
expect(json_ids).to eq([storage_move.id, storage_move_middle.id, storage_move_oldest.id])
end
diff --git a/spec/support/shared_examples/services/packages_shared_examples.rb b/spec/support/shared_examples/services/packages_shared_examples.rb
index f63693dbf26..7a4d7f81e96 100644
--- a/spec/support/shared_examples/services/packages_shared_examples.rb
+++ b/spec/support/shared_examples/services/packages_shared_examples.rb
@@ -76,7 +76,7 @@ RSpec.shared_examples 'returns packages' do |container_type, user_type|
subject
expect(json_response.length).to eq(2)
- expect(json_response.map { |package| package['id'] }).to contain_exactly(package1.id, package2.id)
+ expect(json_response.pluck('id')).to contain_exactly(package1.id, package2.id)
end
end
end
@@ -123,7 +123,7 @@ RSpec.shared_examples 'returns packages with subgroups' do |container_type, user
subject
expect(json_response.length).to eq(3)
- expect(json_response.map { |package| package['id'] }).to contain_exactly(package1.id, package2.id, package3.id)
+ expect(json_response.pluck('id')).to contain_exactly(package1.id, package2.id, package3.id)
end
end
end
@@ -138,7 +138,7 @@ RSpec.shared_examples 'package sorting' do |order_by|
it 'returns the sorted packages' do
subject
- expect(json_response.map { |package| package['id'] }).to eq(packages.map(&:id))
+ expect(json_response.pluck('id')).to eq(packages.map(&:id))
end
end
@@ -148,7 +148,7 @@ RSpec.shared_examples 'package sorting' do |order_by|
it 'returns the sorted packages' do
subject
- expect(json_response.map { |package| package['id'] }).to eq(packages.reverse.map(&:id))
+ expect(json_response.pluck('id')).to eq(packages.reverse.map(&:id))
end
end
end
@@ -225,7 +225,7 @@ RSpec.shared_examples 'filters on each package_type' do |is_project: false|
subject
expect(json_response.length).to eq(1)
- expect(json_response.map { |package| package['package_type'] }).to contain_exactly(package_type)
+ expect(json_response.pluck('package_type')).to contain_exactly(package_type)
end
end
end
@@ -253,7 +253,7 @@ RSpec.shared_examples 'with versionless packages' do
it 'does not return the package' do
subject
- expect(json_response.map { |package| package['id'] }).not_to include(versionless_package.id)
+ expect(json_response.pluck('id')).not_to include(versionless_package.id)
end
end
@@ -268,7 +268,7 @@ RSpec.shared_examples 'with versionless packages' do
it 'returns the package' do
subject
- expect(json_response.map { |package| package['id'] }).to include(versionless_package.id)
+ expect(json_response.pluck('id')).to include(versionless_package.id)
end
end
end
@@ -295,7 +295,7 @@ RSpec.shared_examples 'with status param' do
it 'does not return the package' do
subject
- expect(json_response.map { |package| package['id'] }).not_to include(hidden_package.id)
+ expect(json_response.pluck('id')).not_to include(hidden_package.id)
end
end
@@ -309,7 +309,7 @@ RSpec.shared_examples 'with status param' do
it 'returns the package' do
subject
- expect(json_response.map { |package| package['id'] }).to include(hidden_package.id)
+ expect(json_response.pluck('id')).to include(hidden_package.id)
end
end
end
diff --git a/spec/workers/container_registry/cleanup_worker_spec.rb b/spec/workers/container_registry/cleanup_worker_spec.rb
index 72e1243ccb5..955d2175085 100644
--- a/spec/workers/container_registry/cleanup_worker_spec.rb
+++ b/spec/workers/container_registry/cleanup_worker_spec.rb
@@ -46,6 +46,77 @@ RSpec.describe ContainerRegistry::CleanupWorker, :aggregate_failures, feature_ca
end
end
+ context 'with stale ongoing repair details' do
+ let_it_be(:stale_updated_at) { (described_class::STALE_REPAIR_DETAIL_THRESHOLD + 5.minutes).ago }
+ let_it_be(:recent_updated_at) { (described_class::STALE_REPAIR_DETAIL_THRESHOLD - 5.minutes).ago }
+ let_it_be(:old_repair_detail) { create(:container_registry_data_repair_detail, updated_at: stale_updated_at) }
+ let_it_be(:new_repair_detail) { create(:container_registry_data_repair_detail, updated_at: recent_updated_at) }
+
+ it 'deletes them' do
+ expect { perform }.to change { ContainerRegistry::DataRepairDetail.count }.from(2).to(1)
+ expect(ContainerRegistry::DataRepairDetail.all).to contain_exactly(new_repair_detail)
+ end
+ end
+
+ shared_examples 'does not enqueue record repair detail jobs' do
+ it 'does not enqueue record repair detail jobs' do
+ expect(ContainerRegistry::RecordDataRepairDetailWorker).not_to receive(:perform_with_capacity)
+
+ perform
+ end
+ end
+
+ context 'when on gitlab.com', :saas do
+ context 'when the gitlab api is supported' do
+ let(:relation) { instance_double(ActiveRecord::Relation) }
+
+ before do
+ allow(ContainerRegistry::GitlabApiClient).to receive(:supports_gitlab_api?).and_return(true)
+ allow(Project).to receive(:pending_data_repair_analysis).and_return(relation)
+ end
+
+ context 'when there are pending projects to analyze' do
+ before do
+ allow(relation).to receive(:exists?).and_return(true)
+ end
+
+ it "enqueues record repair detail jobs" do
+ expect(ContainerRegistry::RecordDataRepairDetailWorker).to receive(:perform_with_capacity)
+
+ perform
+ end
+ end
+
+ context 'when there are no pending projects to analyze' do
+ before do
+ allow(relation).to receive(:exists?).and_return(false)
+ end
+
+ it_behaves_like 'does not enqueue record repair detail jobs'
+ end
+ end
+
+ context 'when the Gitlab API is not supported' do
+ before do
+ allow(ContainerRegistry::GitlabApiClient).to receive(:supports_gitlab_api?).and_return(false)
+ end
+
+ it_behaves_like 'does not enqueue record repair detail jobs'
+ end
+ end
+
+ context 'when not on Gitlab.com' do
+ it_behaves_like 'does not enqueue record repair detail jobs'
+ end
+
+ context 'when registry_data_repair_worker feature is disabled' do
+ before do
+ stub_feature_flags(registry_data_repair_worker: false)
+ end
+
+ it_behaves_like 'does not enqueue record repair detail jobs'
+ end
+
context 'for counts logging' do
let_it_be(:delete_started_at) { (described_class::STALE_DELETE_THRESHOLD + 5.minutes).ago }
let_it_be(:stale_delete_container_repository) do
diff --git a/spec/workers/container_registry/record_data_repair_detail_worker_spec.rb b/spec/workers/container_registry/record_data_repair_detail_worker_spec.rb
new file mode 100644
index 00000000000..f107144d397
--- /dev/null
+++ b/spec/workers/container_registry/record_data_repair_detail_worker_spec.rb
@@ -0,0 +1,191 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ContainerRegistry::RecordDataRepairDetailWorker, :aggregate_failures, :clean_gitlab_redis_shared_state,
+ feature_category: :container_registry do
+ include ExclusiveLeaseHelpers
+
+ let(:worker) { described_class.new }
+
+ describe '#perform_work' do
+ subject(:perform_work) { worker.perform_work }
+
+ context 'with no work to do - no projects pending analysis' do
+ it 'will not try to get an exclusive lease and connect to the endpoint' do
+ allow(Project).to receive(:pending_data_repair_analysis).and_return([])
+ expect(::Gitlab::ExclusiveLease).not_to receive(:new)
+
+ expect(::ContainerRegistry::GitlabApiClient).not_to receive(:each_sub_repositories_with_tag_page)
+
+ perform_work
+ end
+ end
+
+ context 'with work to do' do
+ let_it_be(:path) { 'build/cng/docker-alpine' }
+ let_it_be(:group) { create(:group, path: 'build') }
+ let_it_be(:project) { create(:project, name: 'cng', namespace: group) }
+
+ let_it_be(:container_repository) { create(:container_repository, project: project, name: "docker-alpine") }
+ let_it_be(:lease_key) { "container_registry_data_repair_detail_worker:#{project.id}" }
+
+ before do
+ allow(ContainerRegistry::GitlabApiClient).to receive(:each_sub_repositories_with_tag_page)
+ allow(ContainerRegistry::GitlabApiClient).to receive(:supports_gitlab_api?).and_return(true)
+ end
+
+ context 'when on Gitlab.com', :saas do
+ it 'obtains exclusive lease on the project' do
+ expect(Project).to receive(:pending_data_repair_analysis).and_call_original
+ expect_to_obtain_exclusive_lease("container_registry_data_repair_detail_worker:#{project.id}",
+ timeout: described_class::LEASE_TIMEOUT)
+ expect_to_cancel_exclusive_lease("container_registry_data_repair_detail_worker:#{project.id}", 'uuid')
+
+ perform_work
+ end
+
+ it 'queries how many are existing repositories and counts the missing ones' do
+ stub_exclusive_lease("container_registry_data_repair_detail_worker:#{project.id}",
+ timeout: described_class::LEASE_TIMEOUT)
+ allow(ContainerRegistry::GitlabApiClient).to receive(:each_sub_repositories_with_tag_page)
+ .with(path: project.full_path, page_size: 50).and_yield(
+ [
+ { "path" => container_repository.path },
+ { "path" => 'missing1/repository' },
+ { "path" => 'missing2/repository' }
+ ]
+ )
+
+ expect(worker).not_to receive(:log_extra_metadata_on_done)
+ expect { perform_work }.to change { ContainerRegistry::DataRepairDetail.count }.from(0).to(1)
+ expect(ContainerRegistry::DataRepairDetail.first).to have_attributes(project: project, missing_count: 2)
+ end
+
+ it 'logs invalid paths' do
+ stub_exclusive_lease("container_registry_data_repair_detail_worker:#{project.id}",
+ timeout: described_class::LEASE_TIMEOUT)
+ valid_path = ContainerRegistry::Path.new('valid/path')
+ invalid_path = ContainerRegistry::Path.new('invalid/path')
+ allow(valid_path).to receive(:valid?).and_return(true)
+ allow(invalid_path).to receive(:valid?).and_return(false)
+
+ allow(ContainerRegistry::GitlabApiClient).to receive(:each_sub_repositories_with_tag_page)
+ .with(path: project.full_path, page_size: 50).and_yield(
+ [
+ { "path" => valid_path.to_s },
+ { "path" => invalid_path.to_s }
+ ]
+ )
+
+ allow(ContainerRegistry::Path).to receive(:new).with(valid_path.to_s).and_return(valid_path)
+ allow(ContainerRegistry::Path).to receive(:new).with(invalid_path.to_s).and_return(invalid_path)
+
+ expect(worker).to receive(:log_extra_metadata_on_done).with(
+ :invalid_paths_parsed_in_container_repository_repair,
+ "invalid/path"
+ )
+ perform_work
+ end
+
+ it_behaves_like 'an idempotent worker' do
+ it 'creates a data repair detail' do
+ expect { perform_work }.to change { ContainerRegistry::DataRepairDetail.count }.from(0).to(1)
+ expect(project.container_registry_data_repair_detail).to be_present
+ end
+ end
+
+ context 'when the lease cannot be obtained' do
+ before do
+ stub_exclusive_lease_taken(lease_key, timeout: described_class::LEASE_TIMEOUT)
+ end
+
+ it 'logs an error and does not proceed' do
+ expect(worker).to receive(:log_lease_taken)
+ expect(ContainerRegistry::GitlabApiClient).not_to receive(:each_sub_repositories_with_tag_page)
+
+ perform_work
+ end
+
+ it 'does not create the data repair detail' do
+ perform_work
+
+ expect(project.reload.container_registry_data_repair_detail).to be_nil
+ end
+ end
+
+ context 'when an error occurs' do
+ before do
+ stub_exclusive_lease("container_registry_data_repair_detail_worker:#{project.id}",
+ timeout: described_class::LEASE_TIMEOUT)
+ allow(ContainerRegistry::GitlabApiClient).to receive(:each_sub_repositories_with_tag_page)
+ .with(path: project.full_path, page_size: 50).and_raise(RuntimeError)
+ end
+
+ it 'logs the error' do
+ expect(::Gitlab::ErrorTracking).to receive(:log_exception)
+ .with(instance_of(RuntimeError), class: described_class.name)
+
+ perform_work
+ end
+
+ it 'sets the status of the repair detail to failed' do
+ expect { perform_work }.to change { ContainerRegistry::DataRepairDetail.failed.count }.from(0).to(1)
+ expect(project.reload.container_registry_data_repair_detail.failed?).to eq(true)
+ end
+ end
+ end
+
+ context 'when not on Gitlab.com' do
+ it 'will not do anything' do
+ expect(::Gitlab::ExclusiveLease).not_to receive(:new)
+ expect(::ContainerRegistry::GitlabApiClient).not_to receive(:each_sub_repositories_with_tag_page)
+
+ perform_work
+ end
+ end
+ end
+ end
+
+ describe '#max_running_jobs' do
+ subject { worker.max_running_jobs }
+
+ it { is_expected.to eq(described_class::MAX_CAPACITY) }
+ end
+
+ describe '#remaining_work_count' do
+ let_it_be(:pending_projects) do
+ create_list(:project, described_class::MAX_CAPACITY + 2)
+ end
+
+ subject { worker.remaining_work_count }
+
+ context 'when on Gitlab.com', :saas do
+ before do
+ allow(ContainerRegistry::GitlabApiClient).to receive(:supports_gitlab_api?).and_return(true)
+ end
+
+ it { is_expected.to eq(described_class::MAX_CAPACITY + 1) }
+
+ context 'when the Gitlab API is not supported' do
+ before do
+ allow(ContainerRegistry::GitlabApiClient).to receive(:supports_gitlab_api?).and_return(false)
+ end
+
+ it { is_expected.to eq(0) }
+ end
+ end
+
+ context 'when not on Gitlab.com' do
+ it { is_expected.to eq(0) }
+ end
+
+ context 'when registry_data_repair_worker feature is disabled' do
+ before do
+ stub_feature_flags(registry_data_repair_worker: false)
+ end
+
+ it { is_expected.to eq(0) }
+ end
+ end
+end
diff --git a/spec/workers/every_sidekiq_worker_spec.rb b/spec/workers/every_sidekiq_worker_spec.rb
index 4309ec24a9e..2c2cd7e9960 100644
--- a/spec/workers/every_sidekiq_worker_spec.rb
+++ b/spec/workers/every_sidekiq_worker_spec.rb
@@ -191,6 +191,7 @@ RSpec.describe 'Every Sidekiq worker', feature_category: :shared do
'Clusters::Cleanup::ServiceAccountWorker' => 3,
'ContainerExpirationPolicies::CleanupContainerRepositoryWorker' => 0,
'ContainerRegistry::DeleteContainerRepositoryWorker' => 0,
+ 'ContainerRegistry::RecordDataRepairDetailWorker' => 0,
'CreateCommitSignatureWorker' => 3,
'CreateGithubWebhookWorker' => 3,
'CreateNoteDiffFileWorker' => 3,