summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-03-20 15:08:26 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2023-03-20 15:08:26 +0000
commit849e6f56ae6d29014a6d73f0533144adc9619e87 (patch)
tree92cc51ad6dc650ad9284de60699bb430140d3042
parentfa10e47f6e1dced92a7b28dee7fab08abeead777 (diff)
downloadgitlab-ce-849e6f56ae6d29014a6d73f0533144adc9619e87.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.rubocop_todo/layout/argument_alignment.yml50
-rw-r--r--.rubocop_todo/rspec/context_wording.yml1
-rw-r--r--.rubocop_todo/rspec/missing_feature_category.yml1
-rw-r--r--.rubocop_todo/style/redundant_regexp_escape.yml1
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--Gemfile2
-rw-r--r--Gemfile.checksum2
-rw-r--r--Gemfile.lock10
-rw-r--r--app/graphql/mutations/achievements/delete.rb33
-rw-r--r--app/graphql/types/mutation_type.rb1
-rw-r--r--app/helpers/protected_branches_helper.rb2
-rw-r--r--app/helpers/users_helper.rb19
-rw-r--r--app/helpers/visibility_level_helper.rb33
-rw-r--r--app/models/project.rb1
-rw-r--r--app/services/achievements/destroy_service.rb33
-rw-r--r--app/services/releases/create_service.rb6
-rw-r--r--app/uploaders/object_storage/cdn/google_cdn.rb2
-rw-r--r--app/views/layouts/_page.html.haml1
-rw-r--r--config/feature_flags/development/arkose_labs_trial_signup_challenge.yml (renamed from config/feature_flags/development/disable_update_max_seats_worker.yml)8
-rw-r--r--config/feature_flags/development/fix_users_helper_load_max_project_member_accesses.yml8
-rw-r--r--config/initializers/1_settings.rb3
-rw-r--r--data/whats_new/20230222001_15_09.yml10
-rw-r--r--doc/api/graphql/reference/index.md23
-rw-r--r--doc/user/analytics/dora_metrics.md2
-rw-r--r--lib/tasks/gettext.rake46
-rw-r--r--locale/gitlab.pot39
-rw-r--r--spec/graphql/mutations/achievements/delete_spec.rb56
-rw-r--r--spec/helpers/users_helper_spec.rb50
-rw-r--r--spec/helpers/visibility_level_helper_spec.rb19
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml3
-rw-r--r--spec/models/project_spec.rb1
-rw-r--r--spec/requests/api/graphql/mutations/achievements/delete_spec.rb79
-rw-r--r--spec/services/achievements/destroy_service_spec.rb39
-rw-r--r--spec/services/releases/create_service_spec.rb20
-rw-r--r--spec/support/rspec_order_todo.yml2
-rw-r--r--spec/tasks/gettext_rake_spec.rb46
-rw-r--r--spec/uploaders/object_storage/cdn/google_cdn_spec.rb13
-rw-r--r--spec/workers/authorized_project_update/user_refresh_over_user_range_worker_spec.rb4
-rw-r--r--spec/workers/build_hooks_worker_spec.rb4
-rw-r--r--spec/workers/build_queue_worker_spec.rb4
-rw-r--r--spec/workers/ci/job_artifacts/track_artifact_report_worker_spec.rb3
-rw-r--r--spec/workers/concerns/worker_context_spec.rb18
-rw-r--r--spec/workers/deployments/hooks_worker_spec.rb4
-rw-r--r--spec/workers/design_management/new_version_worker_spec.rb8
-rw-r--r--spec/workers/every_sidekiq_worker_spec.rb2
-rw-r--r--spec/workers/integrations/irker_worker_spec.rb9
-rw-r--r--spec/workers/jira_connect/sync_branch_worker_spec.rb4
-rw-r--r--spec/workers/jira_connect/sync_builds_worker_spec.rb4
-rw-r--r--spec/workers/jira_connect/sync_deployments_worker_spec.rb4
-rw-r--r--spec/workers/jira_connect/sync_feature_flags_worker_spec.rb4
-rw-r--r--spec/workers/jira_connect/sync_merge_request_worker_spec.rb4
-rw-r--r--spec/workers/jira_connect/sync_project_worker_spec.rb4
-rw-r--r--spec/workers/merge_requests/delete_source_branch_worker_spec.rb14
-rw-r--r--spec/workers/merge_requests/update_head_pipeline_worker_spec.rb38
-rw-r--r--spec/workers/namespaces/root_statistics_worker_spec.rb4
-rw-r--r--spec/workers/object_pool/destroy_worker_spec.rb10
-rw-r--r--spec/workers/pipeline_hooks_worker_spec.rb4
-rw-r--r--spec/workers/pipeline_metrics_worker_spec.rb20
-rw-r--r--spec/workers/process_commit_worker_spec.rb12
-rw-r--r--spec/workers/projects/inactive_projects_deletion_cron_worker_spec.rb26
-rw-r--r--spec/workers/projects/inactive_projects_deletion_notification_worker_spec.rb9
-rw-r--r--spec/workers/rebase_worker_spec.rb12
-rw-r--r--spec/workers/remote_mirror_notification_worker_spec.rb6
-rw-r--r--spec/workers/remove_expired_members_worker_spec.rb15
-rw-r--r--spec/workers/remove_unaccepted_member_invites_worker_spec.rb56
-rw-r--r--spec/workers/remove_unreferenced_lfs_objects_worker_spec.rb14
-rw-r--r--spec/workers/repository_update_remote_mirror_worker_spec.rb18
-rw-r--r--spec/workers/run_pipeline_schedule_worker_spec.rb8
-rw-r--r--spec/workers/update_head_pipeline_for_merge_request_worker_spec.rb12
-rw-r--r--spec/workers/web_hook_worker_spec.rb4
70 files changed, 678 insertions, 351 deletions
diff --git a/.rubocop_todo/layout/argument_alignment.yml b/.rubocop_todo/layout/argument_alignment.yml
index 4c0f89e9400..fd2317f00e4 100644
--- a/.rubocop_todo/layout/argument_alignment.yml
+++ b/.rubocop_todo/layout/argument_alignment.yml
@@ -1763,23 +1763,6 @@ Layout/ArgumentAlignment:
- 'ee/spec/views/admin/identities/index.html.haml_spec.rb'
- 'ee/spec/views/groups/edit.html.haml_spec.rb'
- 'ee/spec/views/projects/edit.html.haml_spec.rb'
- - 'ee/spec/workers/adjourned_group_deletion_worker_spec.rb'
- - 'ee/spec/workers/analytics/cycle_analytics/consistency_worker_spec.rb'
- - 'ee/spec/workers/analytics/devops_adoption/create_snapshot_worker_spec.rb'
- - 'ee/spec/workers/audit_events/audit_event_streaming_worker_spec.rb'
- - 'ee/spec/workers/concerns/update_orchestration_policy_configuration_spec.rb'
- - 'ee/spec/workers/create_github_webhook_worker_spec.rb'
- - 'ee/spec/workers/ee/projects/inactive_projects_deletion_cron_worker_spec.rb'
- - 'ee/spec/workers/ee/repository_check/batch_worker_spec.rb'
- - 'ee/spec/workers/elastic_index_bulk_cron_worker_spec.rb'
- - 'ee/spec/workers/elastic_index_initial_bulk_cron_worker_spec.rb'
- - 'ee/spec/workers/epics/update_cached_metadata_worker_spec.rb'
- - 'ee/spec/workers/namespaces/sync_namespace_name_worker_spec.rb'
- - 'ee/spec/workers/pull_mirrors/reenable_configuration_worker_spec.rb'
- - 'ee/spec/workers/repository_update_mirror_worker_spec.rb'
- - 'ee/spec/workers/security/orchestration_policy_rule_schedule_namespace_worker_spec.rb'
- - 'ee/spec/workers/security/orchestration_policy_rule_schedule_worker_spec.rb'
- - 'ee/spec/workers/security/process_scan_result_policy_worker_spec.rb'
- 'lib/api/access_requests.rb'
- 'lib/api/admin/plan_limits.rb'
- 'lib/api/alert_management_alerts.rb'
@@ -3073,37 +3056,4 @@ Layout/ArgumentAlignment:
- 'spec/views/projects/tags/index.html.haml_spec.rb'
- 'spec/views/shared/milestones/_issuables.html.haml_spec.rb'
- 'spec/views/shared/runners/_runner_details.html.haml_spec.rb'
- - 'spec/workers/authorized_project_update/user_refresh_over_user_range_worker_spec.rb'
- - 'spec/workers/build_hooks_worker_spec.rb'
- - 'spec/workers/build_queue_worker_spec.rb'
- - 'spec/workers/ci/job_artifacts/track_artifact_report_worker_spec.rb'
- - 'spec/workers/concerns/worker_context_spec.rb'
- - 'spec/workers/deployments/hooks_worker_spec.rb'
- - 'spec/workers/design_management/new_version_worker_spec.rb'
- - 'spec/workers/every_sidekiq_worker_spec.rb'
- - 'spec/workers/integrations/irker_worker_spec.rb'
- - 'spec/workers/jira_connect/sync_branch_worker_spec.rb'
- - 'spec/workers/jira_connect/sync_builds_worker_spec.rb'
- - 'spec/workers/jira_connect/sync_deployments_worker_spec.rb'
- - 'spec/workers/jira_connect/sync_feature_flags_worker_spec.rb'
- - 'spec/workers/jira_connect/sync_merge_request_worker_spec.rb'
- - 'spec/workers/jira_connect/sync_project_worker_spec.rb'
- - 'spec/workers/merge_requests/delete_source_branch_worker_spec.rb'
- - 'spec/workers/merge_requests/update_head_pipeline_worker_spec.rb'
- - 'spec/workers/namespaces/root_statistics_worker_spec.rb'
- - 'spec/workers/object_pool/destroy_worker_spec.rb'
- - 'spec/workers/pipeline_hooks_worker_spec.rb'
- - 'spec/workers/pipeline_metrics_worker_spec.rb'
- - 'spec/workers/process_commit_worker_spec.rb'
- - 'spec/workers/projects/inactive_projects_deletion_cron_worker_spec.rb'
- - 'spec/workers/projects/inactive_projects_deletion_notification_worker_spec.rb'
- - 'spec/workers/rebase_worker_spec.rb'
- - 'spec/workers/remote_mirror_notification_worker_spec.rb'
- - 'spec/workers/remove_expired_members_worker_spec.rb'
- - 'spec/workers/remove_unaccepted_member_invites_worker_spec.rb'
- - 'spec/workers/remove_unreferenced_lfs_objects_worker_spec.rb'
- - 'spec/workers/repository_update_remote_mirror_worker_spec.rb'
- - 'spec/workers/run_pipeline_schedule_worker_spec.rb'
- - 'spec/workers/update_head_pipeline_for_merge_request_worker_spec.rb'
- - 'spec/workers/web_hook_worker_spec.rb'
- 'tooling/danger/suggestor.rb'
diff --git a/.rubocop_todo/rspec/context_wording.yml b/.rubocop_todo/rspec/context_wording.yml
index ccbbc10ad49..cc005fa9121 100644
--- a/.rubocop_todo/rspec/context_wording.yml
+++ b/.rubocop_todo/rspec/context_wording.yml
@@ -3164,7 +3164,6 @@ RSpec/ContextWording:
- 'spec/support_specs/helpers/stub_method_calls_spec.rb'
- 'spec/tasks/cache/clear/redis_spec.rb'
- 'spec/tasks/dev_rake_spec.rb'
- - 'spec/tasks/gettext_rake_spec.rb'
- 'spec/tasks/gitlab/cleanup_rake_spec.rb'
- 'spec/tasks/gitlab/db/validate_config_rake_spec.rb'
- 'spec/tasks/gitlab/db_rake_spec.rb'
diff --git a/.rubocop_todo/rspec/missing_feature_category.yml b/.rubocop_todo/rspec/missing_feature_category.yml
index bbd6cccef0f..af8a427c9f8 100644
--- a/.rubocop_todo/rspec/missing_feature_category.yml
+++ b/.rubocop_todo/rspec/missing_feature_category.yml
@@ -6079,7 +6079,6 @@ RSpec/MissingFeatureCategory:
- 'spec/tasks/admin_mode_spec.rb'
- 'spec/tasks/config_lint_spec.rb'
- 'spec/tasks/dev_rake_spec.rb'
- - 'spec/tasks/gettext_rake_spec.rb'
- 'spec/tasks/gitlab/artifacts/check_rake_spec.rb'
- 'spec/tasks/gitlab/artifacts/migrate_rake_spec.rb'
- 'spec/tasks/gitlab/background_migrations_rake_spec.rb'
diff --git a/.rubocop_todo/style/redundant_regexp_escape.yml b/.rubocop_todo/style/redundant_regexp_escape.yml
index 9a54b73b64e..61592f8f4cd 100644
--- a/.rubocop_todo/style/redundant_regexp_escape.yml
+++ b/.rubocop_todo/style/redundant_regexp_escape.yml
@@ -77,7 +77,6 @@ Style/RedundantRegexpEscape:
- 'lib/gitlab/utils/sanitize_node_link.rb'
- 'lib/gitlab/word_diff/segments/diff_hunk.rb'
- 'lib/product_analytics/tracker.rb'
- - 'lib/tasks/gettext.rake'
- 'lib/tasks/gitlab/info.rake'
- 'qa/spec/runtime/key/ecdsa_spec.rb'
- 'qa/spec/runtime/key/ed25519_spec.rb'
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index 175d99e2170..8999666e07f 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-534e1a1c783059ab7a24ede2c63a53867ba393a2
+1017fbf2f98b23dd93d86173015159fd31df64d0
diff --git a/Gemfile b/Gemfile
index fb2e6b5c35c..3030dcc6363 100644
--- a/Gemfile
+++ b/Gemfile
@@ -102,7 +102,7 @@ gem 'acme-client', '~> 2.0'
gem 'browser', '~> 5.3.1'
# OS detection for usage ping
-gem 'ohai', '~> 16.10'
+gem 'ohai', '~> 17.9'
# GPG
gem 'gpgme', '~> 2.0.22'
diff --git a/Gemfile.checksum b/Gemfile.checksum
index e35974b5e29..a264fe1d13a 100644
--- a/Gemfile.checksum
+++ b/Gemfile.checksum
@@ -396,7 +396,7 @@
{"name":"oauth","version":"0.5.6","platform":"ruby","checksum":"4085fe28e0c5e2434135e00a6555294fd2a4ff96a98d1bdecdcd619fc6368dff"},
{"name":"oauth2","version":"2.0.9","platform":"ruby","checksum":"b21f9defcf52dc1610e0dfab4c868342173dcd707fd15c777d9f4f04e153f7fb"},
{"name":"octokit","version":"4.25.1","platform":"ruby","checksum":"c02092ee82dcdfe84db0e0ea630a70d32becc54245a4f0bacfd21c010df09b96"},
-{"name":"ohai","version":"16.10.6","platform":"ruby","checksum":"b835806e585faea4ac8346b68c722fb5fc29a29f73fd7e3a022f9073132dec22"},
+{"name":"ohai","version":"17.9.0","platform":"ruby","checksum":"c59cf16124c0a6481fb85013ec7ec5b398651b6abed782d3e06ab058ce9a5406"},
{"name":"oj","version":"3.13.23","platform":"ruby","checksum":"206dfdc4020ad9974705037f269cfba211d61b7662a58c717cce771829ccef51"},
{"name":"oj-introspect","version":"0.7.2","platform":"ruby","checksum":"c415a44567ed2870d8e963a69421d9322128e194fab7867e37e54d5a25d5333d"},
{"name":"omniauth","version":"2.1.0","platform":"ruby","checksum":"bff7234f5ec9323622b217c7f26d52f850de0b0e2b8c807c3358fc79fe572300"},
diff --git a/Gemfile.lock b/Gemfile.lock
index 7ef44a9e27f..f71f7f1fb1d 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1000,16 +1000,16 @@ GEM
octokit (4.25.1)
faraday (>= 1, < 3)
sawyer (~> 0.9)
- ohai (16.10.6)
- chef-config (>= 12.8, < 17)
- chef-utils (>= 16.0, < 17)
+ ohai (17.9.0)
+ chef-config (>= 14.12, < 18)
+ chef-utils (>= 16.0, < 18)
ffi (~> 1.9)
ffi-yajl (~> 2.2)
ipaddress
mixlib-cli (>= 1.7.0)
mixlib-config (>= 2.0, < 4.0)
mixlib-log (>= 2.0.1, < 4.0)
- mixlib-shellout (>= 2.0, < 4.0)
+ mixlib-shellout (~> 3.2, >= 3.2.5)
plist (~> 3.1)
train-core
wmi-lite (~> 1.0)
@@ -1801,7 +1801,7 @@ DEPENDENCIES
nokogiri (~> 1.14.2)
oauth2 (~> 2.0)
octokit (~> 4.15)
- ohai (~> 16.10)
+ ohai (~> 17.9)
oj (~> 3.13.21)
oj-introspect (~> 0.7)
omniauth (~> 2.1.0)
diff --git a/app/graphql/mutations/achievements/delete.rb b/app/graphql/mutations/achievements/delete.rb
new file mode 100644
index 00000000000..0b510b44b4e
--- /dev/null
+++ b/app/graphql/mutations/achievements/delete.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Achievements
+ class Delete < BaseMutation
+ graphql_name 'AchievementsDelete'
+
+ include Gitlab::Graphql::Authorize::AuthorizeResource
+
+ field :achievement,
+ ::Types::Achievements::AchievementType,
+ null: true,
+ description: 'Achievement.'
+
+ argument :achievement_id, ::Types::GlobalIDType[::Achievements::Achievement],
+ required: true,
+ description: 'Global ID of the achievement being deleted.'
+
+ authorize :admin_achievement
+
+ def resolve(args)
+ achievement = authorized_find!(id: args[:achievement_id])
+
+ result = ::Achievements::DestroyService.new(current_user, achievement).execute
+ { achievement: result.payload, errors: result.errors }
+ end
+
+ def find_object(id:)
+ GitlabSchema.object_from_id(id, expected_type: ::Achievements::Achievement)
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/mutation_type.rb b/app/graphql/types/mutation_type.rb
index 9bdbdad4386..43ca4f9643d 100644
--- a/app/graphql/types/mutation_type.rb
+++ b/app/graphql/types/mutation_type.rb
@@ -8,6 +8,7 @@ module Types
mount_mutation Mutations::Achievements::Award, alpha: { milestone: '15.10' }
mount_mutation Mutations::Achievements::Create, alpha: { milestone: '15.8' }
+ mount_mutation Mutations::Achievements::Delete, alpha: { milestone: '15.11' }
mount_mutation Mutations::Achievements::Revoke, alpha: { milestone: '15.10' }
mount_mutation Mutations::Admin::SidekiqQueues::DeleteJobs
mount_mutation Mutations::AlertManagement::CreateAlertIssue
diff --git a/app/helpers/protected_branches_helper.rb b/app/helpers/protected_branches_helper.rb
index 07b07bfd33c..bd2a4d1170d 100644
--- a/app/helpers/protected_branches_helper.rb
+++ b/app/helpers/protected_branches_helper.rb
@@ -17,3 +17,5 @@ module ProtectedBranchesHelper
end
end
end
+
+ProtectedBranchesHelper.prepend_mod
diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb
index e0cf7aa61ee..75fefd12565 100644
--- a/app/helpers/users_helper.rb
+++ b/app/helpers/users_helper.rb
@@ -58,12 +58,23 @@ module UsersHelper
end
# Used to preload when you are rendering many projects and checking access
- #
- # rubocop: disable CodeReuse/ActiveRecord: `projects` can be array which also responds to pluck
def load_max_project_member_accesses(projects)
- current_user&.max_member_access_for_project_ids(projects.pluck(:id))
+ # There are two different request store paradigms for max member access and
+ # we need to preload both of them. One is keyed User the other is keyed by
+ # Project. See https://gitlab.com/gitlab-org/gitlab/-/issues/396822
+
+ # rubocop: disable CodeReuse/ActiveRecord: `projects` can be array which also responds to pluck
+ project_ids = projects.pluck(:id)
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ if Feature.enabled?(:fix_users_helper_load_max_project_member_accesses)
+ Preloaders::UserMaxAccessLevelInProjectsPreloader
+ .new(project_ids, current_user)
+ .execute
+ end
+
+ current_user&.max_member_access_for_project_ids(project_ids)
end
- # rubocop: enable CodeReuse/ActiveRecord
def max_project_member_access(project)
current_user&.max_member_access_for_project(project.id) || Gitlab::Access::NO_ACCESS
diff --git a/app/helpers/visibility_level_helper.rb b/app/helpers/visibility_level_helper.rb
index c577e2da1bb..68b15f7e042 100644
--- a/app/helpers/visibility_level_helper.rb
+++ b/app/helpers/visibility_level_helper.rb
@@ -22,7 +22,7 @@ module VisibilityLevelHelper
when Project
project_visibility_level_description(level)
when Group
- group_visibility_level_description(level)
+ group_visibility_level_description(level, form_model)
end
end
@@ -125,22 +125,39 @@ module VisibilityLevelHelper
def project_visibility_level_description(level)
case level
when Gitlab::VisibilityLevel::PRIVATE
- _("Project access must be granted explicitly to each user. If this project is part of a group, access is granted to members of the group.")
+ s_("VisibilityLevel|Project access must be granted explicitly to each user. If this project is part of a group, access is granted to members of the group.")
when Gitlab::VisibilityLevel::INTERNAL
- _("The project can be accessed by any logged in user except external users.")
+ s_("VisibilityLevel|The project can be accessed by any logged in user except external users.")
when Gitlab::VisibilityLevel::PUBLIC
- _("The project can be accessed without any authentication.")
+ s_("VisibilityLevel|The project can be accessed without any authentication.")
end
end
- def group_visibility_level_description(level)
+ def show_updated_public_description_for_setting(group)
+ group && !group.new_record? && Gitlab::CurrentSettings.current_application_settings.try(:should_check_namespace_plan?)
+ end
+
+ def group_visibility_level_description(level, group = nil)
case level
when Gitlab::VisibilityLevel::PRIVATE
- _("The group and its projects can only be viewed by members.")
+ s_("VisibilityLevel|The group and its projects can only be viewed by members.")
when Gitlab::VisibilityLevel::INTERNAL
- _("The group and any internal projects can be viewed by any logged in user except external users.")
+ s_("VisibilityLevel|The group and any internal projects can be viewed by any logged in user except external users.")
when Gitlab::VisibilityLevel::PUBLIC
- _("The group and any public projects can be viewed without any authentication.")
+ unless show_updated_public_description_for_setting(group)
+ return s_('VisibilityLevel|The group and any public projects can be viewed without any authentication.')
+ end
+
+ Kernel.format(
+ s_(
+ 'VisibilityLevel|The group, any public projects, and any of their members, issues, and merge requests can be viewed without authentication. ' \
+ 'Public groups and projects will be indexed by search engines. ' \
+ 'Read more about %{free_user_limit_doc_link_start}free user limits%{link_end}, ' \
+ 'or %{group_billings_link_start}upgrade to a paid tier%{link_end}.'),
+ free_user_limit_doc_link_start: "<a href='#{help_page_path('user/free_user_limit')}' target='_blank' rel='noopener noreferrer'>".html_safe,
+ group_billings_link_start: "<a href='#{group_billings_path(group)}' target='_blank' rel='noopener noreferrer'>".html_safe,
+ link_end: "</a>".html_safe
+ ).html_safe
end
end
diff --git a/app/models/project.rb b/app/models/project.rb
index cb218c0a49f..0c5257065c1 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -168,6 +168,7 @@ class Project < ApplicationRecord
alias_method :parent, :namespace
alias_attribute :parent_id, :namespace_id
+ has_one :catalog_resource, class_name: 'Ci::Catalog::Resource', inverse_of: :project
has_one :last_event, -> { order 'events.created_at DESC' }, class_name: 'Event'
has_many :boards
diff --git a/app/services/achievements/destroy_service.rb b/app/services/achievements/destroy_service.rb
new file mode 100644
index 00000000000..3204adb8e89
--- /dev/null
+++ b/app/services/achievements/destroy_service.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module Achievements
+ class DestroyService
+ attr_reader :current_user, :achievement
+
+ def initialize(current_user, achievement)
+ @current_user = current_user
+ @achievement = achievement
+ end
+
+ def execute
+ return error_no_permissions unless allowed?
+
+ achievement.delete
+ ServiceResponse.success(payload: achievement)
+ end
+
+ private
+
+ def allowed?
+ current_user&.can?(:admin_achievement, achievement)
+ end
+
+ def error_no_permissions
+ error('You have insufficient permissions to delete this achievement')
+ end
+
+ def error(message)
+ ServiceResponse.error(message: Array(message))
+ end
+ end
+end
diff --git a/app/services/releases/create_service.rb b/app/services/releases/create_service.rb
index a3289f9e552..e5883ca06f4 100644
--- a/app/services/releases/create_service.rb
+++ b/app/services/releases/create_service.rb
@@ -18,6 +18,12 @@ module Releases
return tag unless tag.is_a?(Gitlab::Git::Tag)
+ if project.catalog_resource
+ response = Ci::Catalog::ValidateResourceService.new(project, ref).execute
+
+ return error(response.message) if response.error?
+ end
+
create_release(tag, evidence_pipeline)
end
diff --git a/app/uploaders/object_storage/cdn/google_cdn.rb b/app/uploaders/object_storage/cdn/google_cdn.rb
index f1fe62e9db3..f39729357ed 100644
--- a/app/uploaders/object_storage/cdn/google_cdn.rb
+++ b/app/uploaders/object_storage/cdn/google_cdn.rb
@@ -28,7 +28,7 @@ module ObjectStorage
expiration = (Time.current + expiry).utc.to_i
uri = Addressable::URI.parse(cdn_url)
- uri.path = path
+ uri.path = Addressable::URI.encode_component(path, Addressable::URI::CharacterClasses::PATH)
# Use an Array to preserve order: Google CDN needs to have
# Expires, KeyName, and Signature in that order or it will return a 403 error:
# https://cloud.google.com/cdn/docs/troubleshooting-steps#signing
diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml
index 74567af3554..ee3a790fde0 100644
--- a/app/views/layouts/_page.html.haml
+++ b/app/views/layouts/_page.html.haml
@@ -34,7 +34,6 @@
= dispensable_render_if_exists "shared/namespace_user_cap_reached_alert"
= dispensable_render_if_exists "shared/new_user_signups_cap_reached_alert"
= yield :page_level_alert
- = yield :free_user_cap_alert
= yield :group_invite_members_banner
- unless @hide_breadcrumbs
= render "layouts/nav/breadcrumbs"
diff --git a/config/feature_flags/development/disable_update_max_seats_worker.yml b/config/feature_flags/development/arkose_labs_trial_signup_challenge.yml
index ae0fe482ee9..c24a6994045 100644
--- a/config/feature_flags/development/disable_update_max_seats_worker.yml
+++ b/config/feature_flags/development/arkose_labs_trial_signup_challenge.yml
@@ -1,8 +1,8 @@
---
-name: disable_update_max_seats_worker
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/114127
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/382725
+name: arkose_labs_trial_signup_challenge
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/113985
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/395754
milestone: '15.10'
type: development
-group: group::utilization
+group: group::anti-abuse
default_enabled: false
diff --git a/config/feature_flags/development/fix_users_helper_load_max_project_member_accesses.yml b/config/feature_flags/development/fix_users_helper_load_max_project_member_accesses.yml
new file mode 100644
index 00000000000..67d6ab8ef5a
--- /dev/null
+++ b/config/feature_flags/development/fix_users_helper_load_max_project_member_accesses.yml
@@ -0,0 +1,8 @@
+---
+name: fix_users_helper_load_max_project_member_accesses
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/114665
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/396647
+milestone: '15.11'
+type: development
+group: 'group::pipeline execution'
+default_enabled: false
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index 9cb1be45b68..701b117136c 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -761,9 +761,6 @@ Gitlab.ee do
Settings.cron_jobs['ldap_sync_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['ldap_sync_worker']['cron'] ||= '30 1 * * *'
Settings.cron_jobs['ldap_sync_worker']['job_class'] = 'LdapSyncWorker'
- Settings.cron_jobs['update_max_seats_used_for_gitlab_com_subscriptions_worker'] ||= Settingslogic.new({})
- Settings.cron_jobs['update_max_seats_used_for_gitlab_com_subscriptions_worker']['cron'] ||= '0 12 * * *'
- Settings.cron_jobs['update_max_seats_used_for_gitlab_com_subscriptions_worker']['job_class'] = 'UpdateMaxSeatsUsedForGitlabComSubscriptionsWorker'
Settings.cron_jobs['elastic_index_bulk_cron_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['elastic_index_bulk_cron_worker']['cron'] ||= '*/1 * * * *'
Settings.cron_jobs['elastic_index_bulk_cron_worker']['job_class'] ||= 'ElasticIndexBulkCronWorker'
diff --git a/data/whats_new/20230222001_15_09.yml b/data/whats_new/20230222001_15_09.yml
index 217212297bb..12f771f397f 100644
--- a/data/whats_new/20230222001_15_09.yml
+++ b/data/whats_new/20230222001_15_09.yml
@@ -7,7 +7,7 @@
available_in: [Ultimate]
documentation_link: https://docs.gitlab.com/ee/user/permissions.html#custom-roles
image_url: https://img.youtube.com/vi/46cp_-Rtxps/hqdefault.jpg
- published_at: 2023-02-02 # YYYY-MM-DD
+ published_at: 2023-02-22 # YYYY-MM-DD
release: 15.9
- name: Manage license approval policies
description: | # Do not modify this line, instead modify the lines below.
@@ -26,7 +26,7 @@
available_in: [Ultimate]
documentation_link: https://docs.gitlab.com/ee/user/compliance/license_approval_policies.html
image_url: https://img.youtube.com/vi/34qBQ9t8qO8/hqdefault.jpg
- published_at: 2023-02-02 # YYYY-MM-DD
+ published_at: 2023-02-22 # YYYY-MM-DD
release: 15.9
- name: New License Compliance scanner
description: | # Do not modify this line, instead modify the lines below.
@@ -41,7 +41,7 @@
available_in: [Ultimate]
documentation_link: https://docs.gitlab.com/ee/user/compliance/license_scanning_of_cyclonedx_files/
image_url: https://about.gitlab.com/images/15_9/new_license_scanner.png
- published_at: 2023-02-02 # YYYY-MM-DD
+ published_at: 2023-02-22 # YYYY-MM-DD
release: 15.9
- name: Notifications now available in the GitLab for Slack app
description: | # Do not modify this line, instead modify the lines below.
@@ -56,7 +56,7 @@
available_in: [Free, Premium, Ultimate]
documentation_link: https://docs.gitlab.com/ee/user/project/integrations/gitlab_slack_application.html#slack-notifications
image_url: https://about.gitlab.com/images/15_9/slack_notifications_jan_31-optimized.png
- published_at: 2023-02-02 # YYYY-MM-DD
+ published_at: 2023-02-22 # YYYY-MM-DD
release: 15.9
- name: Code Suggestions available in closed beta
description: | # Do not modify this line, instead modify the lines below.
@@ -71,5 +71,5 @@
available_in: [Ultimate]
documentation_link: https://about.gitlab.com/releases/2023/02/22/gitlab-15-9-released/#code-suggestions-available-in-closed-beta
image_url: https://about.gitlab.com/images/15_9/DemoFastApi.gif
- published_at: 2023-02-02 # YYYY-MM-DD
+ published_at: 2023-02-22 # YYYY-MM-DD
release: 15.9
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index 27da9f2b653..312e8894071 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -795,6 +795,29 @@ Input type: `AchievementsCreateInput`
| <a id="mutationachievementscreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationachievementscreateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+### `Mutation.achievementsDelete`
+
+WARNING:
+**Introduced** in 15.11.
+This feature is in Alpha. It can be changed or removed at any time.
+
+Input type: `AchievementsDeleteInput`
+
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationachievementsdeleteachievementid"></a>`achievementId` | [`AchievementsAchievementID!`](#achievementsachievementid) | Global ID of the achievement being deleted. |
+| <a id="mutationachievementsdeleteclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="mutationachievementsdeleteachievement"></a>`achievement` | [`Achievement`](#achievement) | Achievement. |
+| <a id="mutationachievementsdeleteclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
+| <a id="mutationachievementsdeleteerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
+
### `Mutation.achievementsRevoke`
WARNING:
diff --git a/doc/user/analytics/dora_metrics.md b/doc/user/analytics/dora_metrics.md
index b85ec60f00e..0fdb4ea6948 100644
--- a/doc/user/analytics/dora_metrics.md
+++ b/doc/user/analytics/dora_metrics.md
@@ -140,7 +140,7 @@ The DORA metrics are displayed on the following charts:
The table below provides an overview of the DORA metrics' data aggregation in different charts.
-| Metric name | Measured values | Data aggregation in the [Value Streams Dashboard](value_streams_dashboard.md) | Data aggregation in CI/CD analytics charts | Data aggregation in Value stream analytics | Data aggregation in Custom insights reporting |
+| Metric name | Measured values | Data aggregation in the [Value Streams Dashboard](value_streams_dashboard.md) | Data aggregation in [CI/CD analytics charts](ci_cd_analytics.md) | Data aggregation in Value stream analytics | Data aggregation in [Custom insights reporting](../../user/project/insights/index.md#dora-query-parameters) |
|---------------------------|-------------------|-----------------------------------------------------|------------------------|-----------------------|----------|
| Deployment frequency | Number of successful deployments | daily average per month | daily average | daily average | `day` (default) or `month` |
| Lead time for changes | Number of seconds to successfully deliver a commit into production | daily median per month | median time | median time | `day` (default) or `month` |
diff --git a/lib/tasks/gettext.rake b/lib/tasks/gettext.rake
index 17f9414ad52..5b95057488c 100644
--- a/lib/tasks/gettext.rake
+++ b/lib/tasks/gettext.rake
@@ -11,45 +11,23 @@ namespace :gettext do
end
desc 'Regenerate gitlab.pot file'
- task :regenerate do
+ task regenerate: ['gettext:setup'] do
ensure_locale_folder_presence!
- # Clean up folders that do not contain a gitlab.po file
- Pathname.new(locale_path).children.each do |child|
- next unless child.directory?
-
- folder_path = child.to_path
-
- if File.exist?("#{folder_path}/gitlab.po")
- # remove all translated files to speed up finding
- FileUtils.rm Dir["#{folder_path}/gitlab.*"]
- else
- # remove empty translation folders so we don't generate un-needed .po files
- puts "Deleting #{folder_path} as it does not contain a 'gitlab.po' file."
-
- FileUtils.rm_r folder_path
- end
- end
-
# remove the `pot` file to ensure it's completely regenerated
FileUtils.rm_f(pot_file_path)
- Rake::Task['gettext:find'].invoke
-
- # leave only the required changes.
- unless system(*%w(git -c core.hooksPath=/dev/null checkout -- locale/*/gitlab.po))
- raise 'failed to cleanup generated locale/*/gitlab.po files'
- end
+ Rake::Task['gettext:pot:create'].invoke
raise 'gitlab.pot file not generated' unless File.exist?(pot_file_path)
# Remove timestamps from the pot file
pot_content = File.read pot_file_path
- pot_content.gsub!(/^"POT?\-(?:Creation|Revision)\-Date\:.*\n/, '')
+ pot_content.gsub!(/^"POT?-(?:Creation|Revision)-Date:.*\n/, '')
File.write pot_file_path, pot_content
puts <<~MSG
- All done. Please commit the changes to `locale/gitlab.pot`.
+ All done. Please commit the changes to `locale/gitlab.pot`.
MSG
end
@@ -86,19 +64,7 @@ namespace :gettext do
end
end
- task :updated_check do
- # Removing all pre-translated files speeds up `gettext:find` as the
- # files don't need to be merged.
- # Having `LC_MESSAGES/gitlab.mo files present also confuses the output.
- FileUtils.rm Dir['locale/**/gitlab.*']
- FileUtils.rm_f pot_file_path
-
- # `gettext:find` writes touches to temp files to `stderr` which would cause
- # `static-analysis` to report failures. We can ignore these.
- silence_stderr do
- Rake::Task['gettext:find'].invoke
- end
-
+ task updated_check: [:regenerate] do
pot_diff = `git diff -- #{pot_file_path} | grep -E '^(\\+|-)msgid'`.strip
# reset the locale folder for potential next tasks
@@ -159,7 +125,7 @@ namespace :gettext do
def ensure_locale_folder_presence!
unless Dir.exist?(locale_path)
raise <<~MSG
- Cannot find '#{locale_path}' folder. Please ensure you're running this task from the gitlab repo.
+ Cannot find '#{locale_path}' folder. Please ensure you're running this task from the gitlab repo.
MSG
end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index ca757c57f3b..70b7d41de42 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -33673,9 +33673,6 @@ msgstr ""
msgid "Project URL"
msgstr ""
-msgid "Project access must be granted explicitly to each user. If this project is part of a group, access is granted to members of the group."
-msgstr ""
-
msgid "Project access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -43627,15 +43624,6 @@ msgstr ""
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
-msgid "The group and any internal projects can be viewed by any logged in user except external users."
-msgstr ""
-
-msgid "The group and any public projects can be viewed without any authentication."
-msgstr ""
-
-msgid "The group and its projects can only be viewed by members."
-msgstr ""
-
msgid "The group export can be downloaded from:"
msgstr ""
@@ -43795,12 +43783,6 @@ msgstr ""
msgid "The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user."
msgstr ""
-msgid "The project can be accessed by any logged in user except external users."
-msgstr ""
-
-msgid "The project can be accessed without any authentication."
-msgstr ""
-
msgid "The project has already been added to your dashboard."
msgstr ""
@@ -48058,9 +48040,30 @@ msgstr ""
msgid "VisibilityLevel|Private"
msgstr ""
+msgid "VisibilityLevel|Project access must be granted explicitly to each user. If this project is part of a group, access is granted to members of the group."
+msgstr ""
+
msgid "VisibilityLevel|Public"
msgstr ""
+msgid "VisibilityLevel|The group and any internal projects can be viewed by any logged in user except external users."
+msgstr ""
+
+msgid "VisibilityLevel|The group and any public projects can be viewed without any authentication."
+msgstr ""
+
+msgid "VisibilityLevel|The group and its projects can only be viewed by members."
+msgstr ""
+
+msgid "VisibilityLevel|The group, any public projects, and any of their members, issues, and merge requests can be viewed without authentication. Public groups and projects will be indexed by search engines. Read more about %{free_user_limit_doc_link_start}free user limits%{link_end}, or %{group_billings_link_start}upgrade to a paid tier%{link_end}."
+msgstr ""
+
+msgid "VisibilityLevel|The project can be accessed by any logged in user except external users."
+msgstr ""
+
+msgid "VisibilityLevel|The project can be accessed without any authentication."
+msgstr ""
+
msgid "VisibilityLevel|Unknown"
msgstr ""
diff --git a/spec/graphql/mutations/achievements/delete_spec.rb b/spec/graphql/mutations/achievements/delete_spec.rb
new file mode 100644
index 00000000000..0eb6f5a2e6f
--- /dev/null
+++ b/spec/graphql/mutations/achievements/delete_spec.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::Achievements::Delete, feature_category: :user_profile do
+ include GraphqlHelpers
+
+ let_it_be(:developer) { create(:user) }
+ let_it_be(:maintainer) { create(:user) }
+ let_it_be(:recipient) { create(:user) }
+ let_it_be(:group) { create(:group) }
+
+ let(:achievement) { create(:achievement, namespace: group) }
+
+ describe '#resolve' do
+ subject(:resolve_mutation) do
+ described_class.new(object: nil, context: { current_user: current_user }, field: nil).resolve(
+ achievement_id: achievement&.to_global_id
+ )
+ end
+
+ before_all do
+ group.add_developer(developer)
+ group.add_maintainer(maintainer)
+ end
+
+ context 'when the user does not have permission' do
+ let(:current_user) { developer }
+
+ it 'raises an error' do
+ expect { resolve_mutation }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ .with_message(Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR)
+ end
+ end
+
+ context 'when the user has permission' do
+ let(:current_user) { maintainer }
+
+ context 'when the params are invalid' do
+ let(:achievement) { nil }
+
+ it 'returns the validation error' do
+ expect { resolve_mutation }.to raise_error { Gitlab::Graphql::Errors::ArgumentError }
+ end
+ end
+
+ it 'deletes the achievement' do
+ resolve_mutation
+
+ expect(Achievements::Achievement.find_by(id: achievement.id)).to be_nil
+ end
+ end
+ end
+
+ specify { expect(described_class).to require_graphql_authorizations(:admin_achievement) }
+end
diff --git a/spec/helpers/users_helper_spec.rb b/spec/helpers/users_helper_spec.rb
index 2829236f7d1..e1f474a0a3e 100644
--- a/spec/helpers/users_helper_spec.rb
+++ b/spec/helpers/users_helper_spec.rb
@@ -524,4 +524,54 @@ RSpec.describe UsersHelper do
})
end
end
+
+ describe '#load_max_project_member_accesses' do
+ let_it_be(:projects) { create_list(:project, 3) }
+
+ before(:all) do
+ projects.first.add_developer(user)
+ end
+
+ context 'without current_user' do
+ before do
+ allow(helper).to receive(:current_user).and_return(nil)
+ end
+
+ it 'executes no queries' do
+ sample = ActiveRecord::QueryRecorder.new do
+ helper.load_max_project_member_accesses(projects)
+ end
+
+ expect(sample).not_to exceed_query_limit(0)
+ end
+ end
+
+ context 'when current_user is present', :request_store do
+ before do
+ allow(helper).to receive(:current_user).and_return(user)
+ end
+
+ it 'preloads ProjectPolicy#lookup_access_level! and UsersHelper#max_member_project_member_access for current_user in two queries', :aggregate_failures do
+ preload_queries = ActiveRecord::QueryRecorder.new do
+ helper.load_max_project_member_accesses(projects)
+ end
+
+ helper_queries = ActiveRecord::QueryRecorder.new do
+ projects.each do |project|
+ helper.max_project_member_access(project)
+ end
+ end
+
+ access_queries = ActiveRecord::QueryRecorder.new do
+ projects.each do |project|
+ user.can?(:read_code, project)
+ end
+ end
+
+ expect(preload_queries).not_to exceed_query_limit(2)
+ expect(helper_queries).not_to exceed_query_limit(0)
+ expect(access_queries).not_to exceed_query_limit(0)
+ end
+ end
+ end
end
diff --git a/spec/helpers/visibility_level_helper_spec.rb b/spec/helpers/visibility_level_helper_spec.rb
index 2aac0cae0c6..a0bd629e3e6 100644
--- a/spec/helpers/visibility_level_helper_spec.rb
+++ b/spec/helpers/visibility_level_helper_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe VisibilityLevelHelper do
+RSpec.describe VisibilityLevelHelper, feature_category: :system_access do
include ProjectForksHelper
let(:project) { build(:project) }
@@ -78,6 +78,23 @@ RSpec.describe VisibilityLevelHelper do
expect(descriptions.uniq.size).to eq(descriptions.size)
expect(descriptions).to all match /group/i
end
+
+ it 'returns default description for public group' do
+ expect(descriptions[2]).to eq('The group and any public projects can be viewed without any authentication.')
+ end
+
+ context 'when application setting `should_check_namespace_plan` is true', if: Gitlab.ee? do
+ let(:group) { create(:group) }
+ let(:public_option_description) { visibility_level_description(Gitlab::VisibilityLevel::PUBLIC, group) }
+
+ before do
+ allow(Gitlab::CurrentSettings.current_application_settings).to receive(:should_check_namespace_plan?) { true }
+ end
+
+ it 'returns updated description for public visibility option in group general settings' do
+ expect(public_option_description).to match /^The group, any public projects, and any of their members, issues, and merge requests can be viewed without authentication./
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index f6d6a791e8c..bcdbf3d58d0 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -493,6 +493,7 @@ container_repositories:
- project
- name
project:
+- catalog_resource
- external_status_checks
- base_tags
- project_topics
@@ -998,3 +999,5 @@ resource_iteration_events:
iterations_cadence:
- group
- iterations
+catalog_resource:
+ - project
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 15e5db5af60..caaf85c79c3 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -43,6 +43,7 @@ RSpec.describe Project, factory_default: :keep, feature_category: :projects do
it { is_expected.to have_many(:exported_protected_branches) }
it { is_expected.to have_one(:wiki_repository).class_name('Projects::WikiRepository').inverse_of(:project) }
it { is_expected.to have_one(:slack_integration) }
+ it { is_expected.to have_one(:catalog_resource) }
it { is_expected.to have_one(:microsoft_teams_integration) }
it { is_expected.to have_one(:mattermost_integration) }
it { is_expected.to have_one(:hangouts_chat_integration) }
diff --git a/spec/requests/api/graphql/mutations/achievements/delete_spec.rb b/spec/requests/api/graphql/mutations/achievements/delete_spec.rb
new file mode 100644
index 00000000000..276da4f46a8
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/achievements/delete_spec.rb
@@ -0,0 +1,79 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::Achievements::Delete, feature_category: :user_profile do
+ include GraphqlHelpers
+
+ let_it_be(:developer) { create(:user) }
+ let_it_be(:maintainer) { create(:user) }
+ let_it_be(:group) { create(:group) }
+
+ let!(:achievement) { create(:achievement, namespace: group) }
+ let(:mutation) { graphql_mutation(:achievements_delete, params) }
+ let(:achievement_id) { achievement&.to_global_id }
+ let(:params) { { achievement_id: achievement_id } }
+
+ subject { post_graphql_mutation(mutation, current_user: current_user) }
+
+ def mutation_response
+ graphql_mutation_response(:achievements_delete)
+ end
+
+ before_all do
+ group.add_developer(developer)
+ group.add_maintainer(maintainer)
+ end
+
+ context 'when the user does not have permission' do
+ let(:current_user) { developer }
+
+ it_behaves_like 'a mutation that returns a top-level access error'
+
+ it 'does not revoke any achievements' do
+ expect { subject }.not_to change { Achievements::Achievement.count }
+ end
+ end
+
+ context 'when the user has permission' do
+ let(:current_user) { maintainer }
+
+ context 'when the params are invalid' do
+ let(:achievement) { nil }
+
+ it 'returns the validation error' do
+ subject
+
+ expect(graphql_errors.to_s).to include('invalid value for achievementId (Expected value to not be null)')
+ end
+ end
+
+ context 'when the achievement_id is invalid' do
+ let(:achievement_id) { "gid://gitlab/Achievements::Achievement/#{non_existing_record_id}" }
+
+ it 'returns the validation error' do
+ subject
+
+ expect(graphql_errors.to_s)
+ .to include("The resource that you are attempting to access does not exist or you don't have permission")
+ end
+ end
+
+ context 'when the feature flag is disabled' do
+ before do
+ stub_feature_flags(achievements: false)
+ end
+
+ it 'returns the relevant error' do
+ subject
+
+ expect(graphql_errors.to_s)
+ .to include("The resource that you are attempting to access does not exist or you don't have permission")
+ end
+ end
+
+ it 'deletes the achievement' do
+ expect { subject }.to change { Achievements::Achievement.count }.by(-1)
+ end
+ end
+end
diff --git a/spec/services/achievements/destroy_service_spec.rb b/spec/services/achievements/destroy_service_spec.rb
new file mode 100644
index 00000000000..7af10ceec6a
--- /dev/null
+++ b/spec/services/achievements/destroy_service_spec.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Achievements::DestroyService, feature_category: :user_profile do
+ describe '#execute' do
+ let_it_be(:developer) { create(:user) }
+ let_it_be(:maintainer) { create(:user) }
+ let_it_be(:group) { create(:group) }
+
+ let(:achievement) { create(:achievement, namespace: group) }
+
+ subject(:response) { described_class.new(current_user, achievement).execute }
+
+ before_all do
+ group.add_developer(developer)
+ group.add_maintainer(maintainer)
+ end
+
+ context 'when user does not have permission' do
+ let(:current_user) { developer }
+
+ it 'returns an error' do
+ expect(response).to be_error
+ expect(response.message).to match_array(
+ ['You have insufficient permissions to delete this achievement'])
+ end
+ end
+
+ context 'when user has permission' do
+ let(:current_user) { maintainer }
+
+ it 'deletes the achievement' do
+ expect(response).to be_success
+ expect(Achievements::Achievement.find_by(id: achievement.id)).to be_nil
+ end
+ end
+ end
+end
diff --git a/spec/services/releases/create_service_spec.rb b/spec/services/releases/create_service_spec.rb
index 9768ceb12e8..ca5dd912e77 100644
--- a/spec/services/releases/create_service_spec.rb
+++ b/spec/services/releases/create_service_spec.rb
@@ -55,6 +55,26 @@ RSpec.describe Releases::CreateService, feature_category: :continuous_integratio
end
end
+ context 'when project is a catalog resource' do
+ let(:ref) { 'master' }
+ let!(:catalog_resource) { create(:catalog_resource, project: project) }
+
+ context 'and it is valid' do
+ let_it_be(:project) { create(:project, :repository, description: 'our components') }
+
+ it_behaves_like 'a successful release creation'
+ end
+
+ context 'and it is invalid' do
+ it 'raises an error and does not update the release' do
+ result = service.execute
+
+ expect(result[:status]).to eq(:error)
+ expect(result[:message]).to eq('Project must have a description')
+ end
+ end
+ end
+
context 'when ref is provided' do
let(:ref) { 'master' }
let(:tag_name) { 'foobar' }
diff --git a/spec/support/rspec_order_todo.yml b/spec/support/rspec_order_todo.yml
index 74b80c4864c..e36fafdddcc 100644
--- a/spec/support/rspec_order_todo.yml
+++ b/spec/support/rspec_order_todo.yml
@@ -3310,7 +3310,6 @@
- './ee/spec/workers/sync_seat_link_worker_spec.rb'
- './ee/spec/workers/todos_destroyer/confidential_epic_worker_spec.rb'
- './ee/spec/workers/update_all_mirrors_worker_spec.rb'
-- './ee/spec/workers/update_max_seats_used_for_gitlab_com_subscriptions_worker_spec.rb'
- './ee/spec/workers/vulnerabilities/historical_statistics/deletion_worker_spec.rb'
- './ee/spec/workers/vulnerabilities/statistics/adjustment_worker_spec.rb'
- './ee/spec/workers/vulnerabilities/statistics/schedule_worker_spec.rb'
@@ -10049,7 +10048,6 @@
- './spec/tasks/cache/clear/redis_spec.rb'
- './spec/tasks/config_lint_spec.rb'
- './spec/tasks/dev_rake_spec.rb'
-- './spec/tasks/gettext_rake_spec.rb'
- './spec/tasks/gitlab/artifacts/check_rake_spec.rb'
- './spec/tasks/gitlab/artifacts/migrate_rake_spec.rb'
- './spec/tasks/gitlab/background_migrations_rake_spec.rb'
diff --git a/spec/tasks/gettext_rake_spec.rb b/spec/tasks/gettext_rake_spec.rb
index 29caa363f7b..d35beef0484 100644
--- a/spec/tasks/gettext_rake_spec.rb
+++ b/spec/tasks/gettext_rake_spec.rb
@@ -2,7 +2,7 @@
require 'rake_helper'
-RSpec.describe 'gettext', :silence_stdout do
+RSpec.describe 'gettext', :silence_stdout, feature_category: :internationalization do
let(:locale_path) { Rails.root.join('tmp/gettext_spec') }
let(:pot_file_path) { File.join(locale_path, 'gitlab.pot') }
@@ -35,9 +35,16 @@ RSpec.describe 'gettext', :silence_stdout do
end
describe ':regenerate' do
+ let(:locale_nz_path) { File.join(locale_path, 'en_NZ') }
+ let(:po_file_path) { File.join(locale_nz_path, 'gitlab.po') }
+
before do
+ FileUtils.mkdir(locale_nz_path)
+ File.write(po_file_path, fixture_file('valid.po'))
+
+ Rake::Task['gettext:setup'].invoke
# this task takes a *really* long time to complete, so stub it for the spec
- allow(Rake::Task['gettext:find']).to receive(:invoke) { invoke_find.call }
+ allow(Rake::Task['gettext:pot:create']).to receive(:invoke) { invoke_find.call }
end
context 'when the locale folder is not found' do
@@ -53,39 +60,6 @@ RSpec.describe 'gettext', :silence_stdout do
end
end
- context 'where there are existing /**/gitlab.po files' do
- let(:locale_nz_path) { File.join(locale_path, 'en_NZ') }
- let(:po_file_path) { File.join(locale_nz_path, 'gitlab.po') }
-
- let(:invoke_find) { -> { File.write pot_file_path, 'pot file test updates' } }
-
- before do
- FileUtils.mkdir(locale_nz_path)
- File.write(po_file_path, fixture_file('valid.po'))
- end
-
- it 'does not remove that locale' do
- expect { run_rake_task('gettext:regenerate') }
- .not_to change { Dir.exist?(locale_nz_path) }
- end
- end
-
- context 'when there are locale folders without a gitlab.po file' do
- let(:empty_locale_path) { File.join(locale_path, 'en_NZ') }
-
- let(:invoke_find) { -> { File.write pot_file_path, 'pot file test updates' } }
-
- before do
- FileUtils.mkdir(empty_locale_path)
- end
-
- it 'removes those folders' do
- expect { run_rake_task('gettext:regenerate') }
- .to change { Dir.exist?(empty_locale_path) }
- .to eq false
- end
- end
-
context 'when the gitlab.pot file cannot be generated' do
let(:invoke_find) { -> { true } }
@@ -95,7 +69,7 @@ RSpec.describe 'gettext', :silence_stdout do
end
end
- context 'when gettext:find changes the revision dates' do
+ context 'when gettext:pot:create changes the revision dates' do
let(:invoke_find) { -> { File.write pot_file_path, fixture_file('valid.po') } }
before do
diff --git a/spec/uploaders/object_storage/cdn/google_cdn_spec.rb b/spec/uploaders/object_storage/cdn/google_cdn_spec.rb
index 184c664f6dc..96413f622e8 100644
--- a/spec/uploaders/object_storage/cdn/google_cdn_spec.rb
+++ b/spec/uploaders/object_storage/cdn/google_cdn_spec.rb
@@ -99,9 +99,10 @@ RSpec.describe ObjectStorage::CDN::GoogleCDN,
let(:path) { '/path/to/file.txt' }
let(:expiration) { (Time.current + 10.minutes).utc.to_i }
let(:cdn_query_params) { "Expires=#{expiration}&KeyName=#{key_name}" }
+ let(:encoded_path) { Addressable::URI.encode_component(path, Addressable::URI::CharacterClasses::PATH) }
def verify_signature(url, unsigned_url)
- expect(url).to start_with("#{options[:url]}#{path}")
+ expect(url).to start_with("#{options[:url]}#{encoded_path}")
uri = Addressable::URI.parse(url)
query = uri.query_values
@@ -116,6 +117,16 @@ RSpec.describe ObjectStorage::CDN::GoogleCDN,
end
end
+ context 'with UTF-8 characters in path' do
+ let(:path) { "/path/to/©️job🧪" }
+ let(:url) { subject.signed_url(path) }
+ let(:unsigned_url) { "#{options[:url]}#{encoded_path}?#{cdn_query_params}" }
+
+ it 'returns a valid signed URL' do
+ verify_signature(url, unsigned_url)
+ end
+ end
+
context 'with default query parameters' do
let(:url) { subject.signed_url(path) }
let(:unsigned_url) { "#{options[:url]}#{path}?#{cdn_query_params}" }
diff --git a/spec/workers/authorized_project_update/user_refresh_over_user_range_worker_spec.rb b/spec/workers/authorized_project_update/user_refresh_over_user_range_worker_spec.rb
index 081bece09e9..fcc157f9998 100644
--- a/spec/workers/authorized_project_update/user_refresh_over_user_range_worker_spec.rb
+++ b/spec/workers/authorized_project_update/user_refresh_over_user_range_worker_spec.rb
@@ -10,9 +10,7 @@ RSpec.describe AuthorizedProjectUpdate::UserRefreshOverUserRangeWorker, feature_
let(:end_user_id) { start_user_id }
let(:execute_worker) { subject.perform(start_user_id, end_user_id) }
- it_behaves_like 'worker with data consistency',
- described_class,
- data_consistency: :delayed
+ it_behaves_like 'worker with data consistency', described_class, data_consistency: :delayed
describe '#perform' do
context 'checks if project authorization update is required' do
diff --git a/spec/workers/build_hooks_worker_spec.rb b/spec/workers/build_hooks_worker_spec.rb
index f8efc9c455d..adae0417a9a 100644
--- a/spec/workers/build_hooks_worker_spec.rb
+++ b/spec/workers/build_hooks_worker_spec.rb
@@ -42,7 +42,5 @@ RSpec.describe BuildHooksWorker, feature_category: :continuous_integration do
end
end
- it_behaves_like 'worker with data consistency',
- described_class,
- data_consistency: :delayed
+ it_behaves_like 'worker with data consistency', described_class, data_consistency: :delayed
end
diff --git a/spec/workers/build_queue_worker_spec.rb b/spec/workers/build_queue_worker_spec.rb
index 1f3640e7496..079e11acde3 100644
--- a/spec/workers/build_queue_worker_spec.rb
+++ b/spec/workers/build_queue_worker_spec.rb
@@ -24,7 +24,5 @@ RSpec.describe BuildQueueWorker, feature_category: :continuous_integration do
end
end
- it_behaves_like 'worker with data consistency',
- described_class,
- data_consistency: :sticky
+ it_behaves_like 'worker with data consistency', described_class, data_consistency: :sticky
end
diff --git a/spec/workers/ci/job_artifacts/track_artifact_report_worker_spec.rb b/spec/workers/ci/job_artifacts/track_artifact_report_worker_spec.rb
index bbc2bcf9ac9..9c3d249c6aa 100644
--- a/spec/workers/ci/job_artifacts/track_artifact_report_worker_spec.rb
+++ b/spec/workers/ci/job_artifacts/track_artifact_report_worker_spec.rb
@@ -9,8 +9,7 @@ RSpec.describe Ci::JobArtifacts::TrackArtifactReportWorker, feature_category: :c
let_it_be(:user) { create(:user) }
let_it_be(:pipeline) do
- create(:ci_pipeline, :with_test_reports, :with_coverage_reports,
- project: project, user: user)
+ create(:ci_pipeline, :with_test_reports, :with_coverage_reports, project: project, user: user)
end
subject(:perform) { described_class.new.perform(pipeline_id) }
diff --git a/spec/workers/concerns/worker_context_spec.rb b/spec/workers/concerns/worker_context_spec.rb
index 0bbe14842bb..700d9e37a55 100644
--- a/spec/workers/concerns/worker_context_spec.rb
+++ b/spec/workers/concerns/worker_context_spec.rb
@@ -73,9 +73,11 @@ RSpec.describe WorkerContext, feature_category: :shared do
describe '.bulk_perform_async_with_contexts' do
subject do
- worker.bulk_perform_async_with_contexts(%w(hello world),
- context_proc: -> (_) { { user: build_stubbed(:user) } },
- arguments_proc: -> (word) { word })
+ worker.bulk_perform_async_with_contexts(
+ %w(hello world),
+ context_proc: -> (_) { { user: build_stubbed(:user) } },
+ arguments_proc: -> (word) { word }
+ )
end
it 'calls bulk_perform_async with the arguments' do
@@ -89,10 +91,12 @@ RSpec.describe WorkerContext, feature_category: :shared do
describe '.bulk_perform_in_with_contexts' do
subject do
- worker.bulk_perform_in_with_contexts(10.minutes,
- %w(hello world),
- context_proc: -> (_) { { user: build_stubbed(:user) } },
- arguments_proc: -> (word) { word })
+ worker.bulk_perform_in_with_contexts(
+ 10.minutes,
+ %w(hello world),
+ context_proc: -> (_) { { user: build_stubbed(:user) } },
+ arguments_proc: -> (word) { word }
+ )
end
it 'calls bulk_perform_in with the arguments and delay' do
diff --git a/spec/workers/deployments/hooks_worker_spec.rb b/spec/workers/deployments/hooks_worker_spec.rb
index 51614f8b0cb..e620ed6e05c 100644
--- a/spec/workers/deployments/hooks_worker_spec.rb
+++ b/spec/workers/deployments/hooks_worker_spec.rb
@@ -60,8 +60,6 @@ RSpec.describe Deployments::HooksWorker, feature_category: :continuous_delivery
worker.perform(deployment_id: deployment.id, status_changed_at: status_changed_at)
end
- it_behaves_like 'worker with data consistency',
- described_class,
- data_consistency: :delayed
+ it_behaves_like 'worker with data consistency', described_class, data_consistency: :delayed
end
end
diff --git a/spec/workers/design_management/new_version_worker_spec.rb b/spec/workers/design_management/new_version_worker_spec.rb
index afc908d925a..baf6409a64f 100644
--- a/spec/workers/design_management/new_version_worker_spec.rb
+++ b/spec/workers/design_management/new_version_worker_spec.rb
@@ -57,9 +57,11 @@ RSpec.describe DesignManagement::NewVersionWorker, feature_category: :design_man
context 'the version includes multiple types of action' do
let_it_be(:version) do
- create(:design_version, :with_lfs_file,
- created_designs: create_list(:design, 1, :with_lfs_file),
- modified_designs: create_list(:design, 1))
+ create(
+ :design_version, :with_lfs_file,
+ created_designs: create_list(:design, 1, :with_lfs_file),
+ modified_designs: create_list(:design, 1)
+ )
end
it 'creates two system notes' do
diff --git a/spec/workers/every_sidekiq_worker_spec.rb b/spec/workers/every_sidekiq_worker_spec.rb
index f080e2ef1c3..86e50bf3f97 100644
--- a/spec/workers/every_sidekiq_worker_spec.rb
+++ b/spec/workers/every_sidekiq_worker_spec.rb
@@ -493,7 +493,7 @@ RSpec.describe 'Every Sidekiq worker', feature_category: :shared do
it 'uses specified numbers of retries for workers with exceptions encoded here', :aggregate_failures do
retry_exception_workers.each do |worker|
expect(worker.retries).to eq(retry_exceptions[worker.klass.to_s]),
- "#{worker.klass} has #{worker.retries} retries, expected #{retry_exceptions[worker.klass]}"
+ "#{worker.klass} has #{worker.retries} retries, expected #{retry_exceptions[worker.klass]}"
end
end
end
diff --git a/spec/workers/integrations/irker_worker_spec.rb b/spec/workers/integrations/irker_worker_spec.rb
index 257a6f72709..7a51e9cfe47 100644
--- a/spec/workers/integrations/irker_worker_spec.rb
+++ b/spec/workers/integrations/irker_worker_spec.rb
@@ -88,10 +88,11 @@ RSpec.describe Integrations::IrkerWorker, '#perform', feature_category: :integra
context 'with new commits to existing branch' do
it 'sends a correct message with a compare url' do
- compare_url = Gitlab::Routing.url_helpers
- .project_compare_url(project,
- from: Commit.truncate_sha(push_data[:before]),
- to: Commit.truncate_sha(push_data[:after]))
+ compare_url = Gitlab::Routing.url_helpers.project_compare_url(
+ project,
+ from: Commit.truncate_sha(push_data[:before]),
+ to: Commit.truncate_sha(push_data[:after])
+ )
message = "pushed #{push_data['total_commits_count']} " \
"new commits to master: #{compare_url}"
diff --git a/spec/workers/jira_connect/sync_branch_worker_spec.rb b/spec/workers/jira_connect/sync_branch_worker_spec.rb
index 54b1915b253..1c2661ad0e5 100644
--- a/spec/workers/jira_connect/sync_branch_worker_spec.rb
+++ b/spec/workers/jira_connect/sync_branch_worker_spec.rb
@@ -5,9 +5,7 @@ require 'spec_helper'
RSpec.describe JiraConnect::SyncBranchWorker, feature_category: :integrations do
include AfterNextHelpers
- it_behaves_like 'worker with data consistency',
- described_class,
- data_consistency: :delayed
+ it_behaves_like 'worker with data consistency', described_class, data_consistency: :delayed
describe '#perform' do
let_it_be(:group) { create(:group) }
diff --git a/spec/workers/jira_connect/sync_builds_worker_spec.rb b/spec/workers/jira_connect/sync_builds_worker_spec.rb
index 6ef15b084a3..8c694fe33bd 100644
--- a/spec/workers/jira_connect/sync_builds_worker_spec.rb
+++ b/spec/workers/jira_connect/sync_builds_worker_spec.rb
@@ -5,9 +5,7 @@ require 'spec_helper'
RSpec.describe ::JiraConnect::SyncBuildsWorker, feature_category: :integrations do
include AfterNextHelpers
- it_behaves_like 'worker with data consistency',
- described_class,
- data_consistency: :delayed
+ it_behaves_like 'worker with data consistency', described_class, data_consistency: :delayed
describe '#perform' do
let_it_be(:pipeline) { create(:ci_pipeline) }
diff --git a/spec/workers/jira_connect/sync_deployments_worker_spec.rb b/spec/workers/jira_connect/sync_deployments_worker_spec.rb
index 2e72a94bc1e..39609f331d0 100644
--- a/spec/workers/jira_connect/sync_deployments_worker_spec.rb
+++ b/spec/workers/jira_connect/sync_deployments_worker_spec.rb
@@ -5,9 +5,7 @@ require 'spec_helper'
RSpec.describe ::JiraConnect::SyncDeploymentsWorker, feature_category: :integrations do
include AfterNextHelpers
- it_behaves_like 'worker with data consistency',
- described_class,
- data_consistency: :delayed
+ it_behaves_like 'worker with data consistency', described_class, data_consistency: :delayed
describe '#perform' do
let_it_be(:deployment) { create(:deployment) }
diff --git a/spec/workers/jira_connect/sync_feature_flags_worker_spec.rb b/spec/workers/jira_connect/sync_feature_flags_worker_spec.rb
index c2dbd52398f..cc3867d26c1 100644
--- a/spec/workers/jira_connect/sync_feature_flags_worker_spec.rb
+++ b/spec/workers/jira_connect/sync_feature_flags_worker_spec.rb
@@ -5,9 +5,7 @@ require 'spec_helper'
RSpec.describe ::JiraConnect::SyncFeatureFlagsWorker, feature_category: :integrations do
include AfterNextHelpers
- it_behaves_like 'worker with data consistency',
- described_class,
- data_consistency: :delayed
+ it_behaves_like 'worker with data consistency', described_class, data_consistency: :delayed
describe '#perform' do
let_it_be(:feature_flag) { create(:operations_feature_flag) }
diff --git a/spec/workers/jira_connect/sync_merge_request_worker_spec.rb b/spec/workers/jira_connect/sync_merge_request_worker_spec.rb
index 23abb915d68..117dfe49b62 100644
--- a/spec/workers/jira_connect/sync_merge_request_worker_spec.rb
+++ b/spec/workers/jira_connect/sync_merge_request_worker_spec.rb
@@ -5,9 +5,7 @@ require 'spec_helper'
RSpec.describe JiraConnect::SyncMergeRequestWorker, feature_category: :integrations do
include AfterNextHelpers
- it_behaves_like 'worker with data consistency',
- described_class,
- data_consistency: :delayed
+ it_behaves_like 'worker with data consistency', described_class, data_consistency: :delayed
describe '#perform' do
let_it_be(:group) { create(:group) }
diff --git a/spec/workers/jira_connect/sync_project_worker_spec.rb b/spec/workers/jira_connect/sync_project_worker_spec.rb
index afd56a3b5c1..f559a3e1c12 100644
--- a/spec/workers/jira_connect/sync_project_worker_spec.rb
+++ b/spec/workers/jira_connect/sync_project_worker_spec.rb
@@ -5,9 +5,7 @@ require 'spec_helper'
RSpec.describe JiraConnect::SyncProjectWorker, factory_default: :keep, feature_category: :integrations do
include AfterNextHelpers
- it_behaves_like 'worker with data consistency',
- described_class,
- data_consistency: :delayed
+ it_behaves_like 'worker with data consistency', described_class, data_consistency: :delayed
describe '#perform' do
let_it_be(:project) { create_default(:project).freeze }
diff --git a/spec/workers/merge_requests/delete_source_branch_worker_spec.rb b/spec/workers/merge_requests/delete_source_branch_worker_spec.rb
index d8e49f444a9..57f8cfbfb83 100644
--- a/spec/workers/merge_requests/delete_source_branch_worker_spec.rb
+++ b/spec/workers/merge_requests/delete_source_branch_worker_spec.rb
@@ -12,8 +12,11 @@ RSpec.describe MergeRequests::DeleteSourceBranchWorker, feature_category: :sourc
describe '#perform' do
before do
allow_next_instance_of(::Projects::DeleteBranchWorker) do |instance|
- allow(instance).to receive(:perform).with(merge_request.source_project.id, user.id,
- merge_request.source_branch)
+ allow(instance).to receive(:perform).with(
+ merge_request.source_project.id,
+ user.id,
+ merge_request.source_branch
+ )
end
end
@@ -36,8 +39,11 @@ RSpec.describe MergeRequests::DeleteSourceBranchWorker, feature_category: :sourc
context 'with existing user and merge request' do
it 'calls delete branch worker' do
expect_next_instance_of(::Projects::DeleteBranchWorker) do |instance|
- expect(instance).to receive(:perform).with(merge_request.source_project.id, user.id,
- merge_request.source_branch)
+ expect(instance).to receive(:perform).with(
+ merge_request.source_project.id,
+ user.id,
+ merge_request.source_branch
+ )
end
worker.perform(merge_request.id, sha, user.id)
diff --git a/spec/workers/merge_requests/update_head_pipeline_worker_spec.rb b/spec/workers/merge_requests/update_head_pipeline_worker_spec.rb
index 912afb59412..b65bd4eb1db 100644
--- a/spec/workers/merge_requests/update_head_pipeline_worker_spec.rb
+++ b/spec/workers/merge_requests/update_head_pipeline_worker_spec.rb
@@ -74,9 +74,12 @@ RSpec.describe MergeRequests::UpdateHeadPipelineWorker, feature_category: :code_
context 'when there is no pipeline for source branch' do
it "does not update merge request head pipeline" do
- merge_request = create(:merge_request, source_branch: 'feature',
- target_branch: "branch_1",
- source_project: project)
+ merge_request = create(
+ :merge_request,
+ source_branch: 'feature',
+ target_branch: "branch_1",
+ source_project: project
+ )
subject
@@ -96,10 +99,13 @@ RSpec.describe MergeRequests::UpdateHeadPipelineWorker, feature_category: :code_
end
it 'updates head pipeline for merge request' do
- merge_request = create(:merge_request, source_branch: 'feature',
- target_branch: "master",
- source_project: project,
- target_project: target_project)
+ merge_request = create(
+ :merge_request,
+ source_branch: 'feature',
+ target_branch: "master",
+ source_project: project,
+ target_project: target_project
+ )
subject
@@ -109,9 +115,12 @@ RSpec.describe MergeRequests::UpdateHeadPipelineWorker, feature_category: :code_
context 'when the pipeline is not the latest for the branch' do
it 'does not update merge request head pipeline' do
- merge_request = create(:merge_request, source_branch: 'master',
- target_branch: "branch_1",
- source_project: project)
+ merge_request = create(
+ :merge_request,
+ source_branch: 'master',
+ target_branch: "branch_1",
+ source_project: project
+ )
create(:ci_pipeline, project: pipeline.project, ref: pipeline.ref)
@@ -127,9 +136,12 @@ RSpec.describe MergeRequests::UpdateHeadPipelineWorker, feature_category: :code_
end
it 'updates merge request head pipeline reference' do
- merge_request = create(:merge_request, source_branch: 'master',
- target_branch: 'feature',
- source_project: project)
+ merge_request = create(
+ :merge_request,
+ source_branch: 'master',
+ target_branch: 'feature',
+ source_project: project
+ )
subject
diff --git a/spec/workers/namespaces/root_statistics_worker_spec.rb b/spec/workers/namespaces/root_statistics_worker_spec.rb
index 8409fffca26..edea9132850 100644
--- a/spec/workers/namespaces/root_statistics_worker_spec.rb
+++ b/spec/workers/namespaces/root_statistics_worker_spec.rb
@@ -90,9 +90,7 @@ RSpec.describe Namespaces::RootStatisticsWorker, '#perform', feature_category: :
end
end
- it_behaves_like 'worker with data consistency',
- described_class,
- data_consistency: :sticky
+ it_behaves_like 'worker with data consistency', described_class, data_consistency: :sticky
it 'has the `until_executed` deduplicate strategy' do
expect(described_class.get_deduplicate_strategy).to eq(:until_executed)
diff --git a/spec/workers/object_pool/destroy_worker_spec.rb b/spec/workers/object_pool/destroy_worker_spec.rb
index f83d3814c63..7db3404ed36 100644
--- a/spec/workers/object_pool/destroy_worker_spec.rb
+++ b/spec/workers/object_pool/destroy_worker_spec.rb
@@ -16,9 +16,13 @@ RSpec.describe ObjectPool::DestroyWorker, feature_category: :shared do
subject { described_class.new }
it 'requests Gitaly to remove the object pool' do
- expect(Gitlab::GitalyClient).to receive(:call)
- .with(pool.shard_name, :object_pool_service, :delete_object_pool,
- Object, timeout: Gitlab::GitalyClient.long_timeout)
+ expect(Gitlab::GitalyClient).to receive(:call).with(
+ pool.shard_name,
+ :object_pool_service,
+ :delete_object_pool,
+ Object,
+ timeout: Gitlab::GitalyClient.long_timeout
+ )
subject.perform(pool.id)
end
diff --git a/spec/workers/pipeline_hooks_worker_spec.rb b/spec/workers/pipeline_hooks_worker_spec.rb
index a8b0f91bf7d..7a85038d946 100644
--- a/spec/workers/pipeline_hooks_worker_spec.rb
+++ b/spec/workers/pipeline_hooks_worker_spec.rb
@@ -37,7 +37,5 @@ RSpec.describe PipelineHooksWorker, feature_category: :continuous_integration do
end
end
- it_behaves_like 'worker with data consistency',
- described_class,
- data_consistency: :delayed
+ it_behaves_like 'worker with data consistency', described_class, data_consistency: :delayed
end
diff --git a/spec/workers/pipeline_metrics_worker_spec.rb b/spec/workers/pipeline_metrics_worker_spec.rb
index f7b397d91a6..7bd98f8f55d 100644
--- a/spec/workers/pipeline_metrics_worker_spec.rb
+++ b/spec/workers/pipeline_metrics_worker_spec.rb
@@ -6,19 +6,19 @@ RSpec.describe PipelineMetricsWorker, feature_category: :continuous_integration
let(:project) { create(:project, :repository) }
let!(:merge_request) do
- create(:merge_request, source_project: project,
- source_branch: pipeline.ref,
- head_pipeline: pipeline)
+ create(:merge_request, source_project: project, source_branch: pipeline.ref, head_pipeline: pipeline)
end
let(:pipeline) do
- create(:ci_empty_pipeline,
- status: status,
- project: project,
- ref: 'master',
- sha: project.repository.commit('master').id,
- started_at: 1.hour.ago,
- finished_at: Time.current)
+ create(
+ :ci_empty_pipeline,
+ status: status,
+ project: project,
+ ref: 'master',
+ sha: project.repository.commit('master').id,
+ started_at: 1.hour.ago,
+ finished_at: Time.current
+ )
end
let(:status) { 'pending' }
diff --git a/spec/workers/process_commit_worker_spec.rb b/spec/workers/process_commit_worker_spec.rb
index 1fc77c42cbc..c95119b0d02 100644
--- a/spec/workers/process_commit_worker_spec.rb
+++ b/spec/workers/process_commit_worker_spec.rb
@@ -82,11 +82,13 @@ RSpec.describe ProcessCommitWorker, feature_category: :source_code_management do
context 'when commit is a merge request merge commit to the default branch' do
let(:merge_request) do
- create(:merge_request,
- description: "Closes #{issue.to_reference}",
- source_branch: 'feature-merged',
- target_branch: 'master',
- source_project: project)
+ create(
+ :merge_request,
+ description: "Closes #{issue.to_reference}",
+ source_branch: 'feature-merged',
+ target_branch: 'master',
+ source_project: project
+ )
end
let(:commit) do
diff --git a/spec/workers/projects/inactive_projects_deletion_cron_worker_spec.rb b/spec/workers/projects/inactive_projects_deletion_cron_worker_spec.rb
index 15234827efa..68af5e61e3b 100644
--- a/spec/workers/projects/inactive_projects_deletion_cron_worker_spec.rb
+++ b/spec/workers/projects/inactive_projects_deletion_cron_worker_spec.rb
@@ -92,8 +92,11 @@ RSpec.describe Projects::InactiveProjectsDeletionCronWorker, feature_category: :
it 'invokes Projects::InactiveProjectsDeletionNotificationWorker for inactive projects' do
Gitlab::Redis::SharedState.with do |redis|
- expect(redis).to receive(:hset).with('inactive_projects_deletion_warning_email_notified',
- "project:#{inactive_large_project.id}", Date.current)
+ expect(redis).to receive(:hset).with(
+ 'inactive_projects_deletion_warning_email_notified',
+ "project:#{inactive_large_project.id}",
+ Date.current
+ )
end
expect(::Projects::InactiveProjectsDeletionNotificationWorker).to receive(:perform_async).with(
inactive_large_project.id, deletion_date).and_call_original
@@ -104,8 +107,11 @@ RSpec.describe Projects::InactiveProjectsDeletionCronWorker, feature_category: :
it 'does not invoke InactiveProjectsDeletionNotificationWorker for already notified inactive projects' do
Gitlab::Redis::SharedState.with do |redis|
- redis.hset('inactive_projects_deletion_warning_email_notified', "project:#{inactive_large_project.id}",
- Date.current.to_s)
+ redis.hset(
+ 'inactive_projects_deletion_warning_email_notified',
+ "project:#{inactive_large_project.id}",
+ Date.current.to_s
+ )
end
expect(::Projects::InactiveProjectsDeletionNotificationWorker).not_to receive(:perform_async)
@@ -116,8 +122,11 @@ RSpec.describe Projects::InactiveProjectsDeletionCronWorker, feature_category: :
it 'invokes Projects::DestroyService for projects that are inactive even after being notified' do
Gitlab::Redis::SharedState.with do |redis|
- redis.hset('inactive_projects_deletion_warning_email_notified', "project:#{inactive_large_project.id}",
- 15.months.ago.to_date.to_s)
+ redis.hset(
+ 'inactive_projects_deletion_warning_email_notified',
+ "project:#{inactive_large_project.id}",
+ 15.months.ago.to_date.to_s
+ )
end
expect(::Projects::InactiveProjectsDeletionNotificationWorker).not_to receive(:perform_async)
@@ -129,8 +138,9 @@ RSpec.describe Projects::InactiveProjectsDeletionCronWorker, feature_category: :
expect(inactive_large_project.reload.pending_delete).to eq(true)
Gitlab::Redis::SharedState.with do |redis|
- expect(redis.hget('inactive_projects_deletion_warning_email_notified',
- "project:#{inactive_large_project.id}")).to be_nil
+ expect(
+ redis.hget('inactive_projects_deletion_warning_email_notified', "project:#{inactive_large_project.id}")
+ ).to be_nil
end
end
diff --git a/spec/workers/projects/inactive_projects_deletion_notification_worker_spec.rb b/spec/workers/projects/inactive_projects_deletion_notification_worker_spec.rb
index 28668188497..2ac2b5d0795 100644
--- a/spec/workers/projects/inactive_projects_deletion_notification_worker_spec.rb
+++ b/spec/workers/projects/inactive_projects_deletion_notification_worker_spec.rb
@@ -22,14 +22,15 @@ RSpec.describe Projects::InactiveProjectsDeletionNotificationWorker, feature_cat
worker.perform(project.id, deletion_date)
Gitlab::Redis::SharedState.with do |redis|
- expect(redis.hget('inactive_projects_deletion_warning_email_notified',
- "project:#{project.id}")).to eq(Date.current.to_s)
+ expect(
+ redis.hget('inactive_projects_deletion_warning_email_notified', "project:#{project.id}")
+ ).to eq(Date.current.to_s)
end
end
it 'rescues and logs the exception if project does not exist' do
- expect(Gitlab::ErrorTracking).to receive(:log_exception).with(instance_of(ActiveRecord::RecordNotFound),
- { project_id: non_existing_project_id })
+ expect(Gitlab::ErrorTracking).to receive(:log_exception)
+ .with(instance_of(ActiveRecord::RecordNotFound), { project_id: non_existing_project_id })
worker.perform(non_existing_project_id, deletion_date)
end
diff --git a/spec/workers/rebase_worker_spec.rb b/spec/workers/rebase_worker_spec.rb
index eec221094e6..ee8fd8b7461 100644
--- a/spec/workers/rebase_worker_spec.rb
+++ b/spec/workers/rebase_worker_spec.rb
@@ -10,11 +10,13 @@ RSpec.describe RebaseWorker, '#perform', feature_category: :source_code_manageme
let(:forked_project) { fork_project(upstream_project, nil, repository: true) }
let(:merge_request) do
- create(:merge_request,
- source_project: forked_project,
- source_branch: 'feature_conflict',
- target_project: upstream_project,
- target_branch: 'master')
+ create(
+ :merge_request,
+ source_project: forked_project,
+ source_branch: 'feature_conflict',
+ target_project: upstream_project,
+ target_branch: 'master'
+ )
end
it 'sets the correct project for running hooks' do
diff --git a/spec/workers/remote_mirror_notification_worker_spec.rb b/spec/workers/remote_mirror_notification_worker_spec.rb
index 46f44d0047b..e7c32d79457 100644
--- a/spec/workers/remote_mirror_notification_worker_spec.rb
+++ b/spec/workers/remote_mirror_notification_worker_spec.rb
@@ -30,8 +30,10 @@ RSpec.describe RemoteMirrorNotificationWorker, :mailer, feature_category: :sourc
end
it 'does nothing when a notification has already been sent' do
- mirror.update_columns(last_error: "There was a problem fetching",
- error_notification_sent: true)
+ mirror.update_columns(
+ last_error: "There was a problem fetching",
+ error_notification_sent: true
+ )
expect(NotificationService).not_to receive(:new)
diff --git a/spec/workers/remove_expired_members_worker_spec.rb b/spec/workers/remove_expired_members_worker_spec.rb
index 354ce3fc9b4..f77a078750d 100644
--- a/spec/workers/remove_expired_members_worker_spec.rb
+++ b/spec/workers/remove_expired_members_worker_spec.rb
@@ -35,8 +35,10 @@ RSpec.describe RemoveExpiredMembersWorker, feature_category: :system_access do
new_job = Sidekiq::Worker.jobs.last
- expect(new_job).to include('meta.project' => expired_project_member.project.full_path,
- 'meta.user' => expired_project_member.user.username)
+ expect(new_job).to include(
+ 'meta.project' => expired_project_member.project.full_path,
+ 'meta.user' => expired_project_member.user.username
+ )
end
end
@@ -60,8 +62,7 @@ RSpec.describe RemoveExpiredMembersWorker, feature_category: :system_access do
worker.perform
expect(
- Users::GhostUserMigration.where(user: expired_project_bot,
- initiator_user: nil)
+ Users::GhostUserMigration.where(user: expired_project_bot, initiator_user: nil)
).to be_exists
end
end
@@ -116,8 +117,10 @@ RSpec.describe RemoveExpiredMembersWorker, feature_category: :system_access do
new_job = Sidekiq::Worker.jobs.last
- expect(new_job).to include('meta.root_namespace' => expired_group_member.group.full_path,
- 'meta.user' => expired_group_member.user.username)
+ expect(new_job).to include(
+ 'meta.root_namespace' => expired_group_member.group.full_path,
+ 'meta.user' => expired_group_member.user.username
+ )
end
end
diff --git a/spec/workers/remove_unaccepted_member_invites_worker_spec.rb b/spec/workers/remove_unaccepted_member_invites_worker_spec.rb
index 97ddf9223b3..5173967c57a 100644
--- a/spec/workers/remove_unaccepted_member_invites_worker_spec.rb
+++ b/spec/workers/remove_unaccepted_member_invites_worker_spec.rb
@@ -13,15 +13,19 @@ RSpec.describe RemoveUnacceptedMemberInvitesWorker, feature_category: :system_ac
it 'removes unaccepted members', :aggregate_failures do
unaccepted_group_invitee = create(
- :group_member, invite_token: 't0ken',
- invite_email: 'group_invitee@example.com',
- user: nil,
- created_at: Time.current - 5.days)
+ :group_member,
+ invite_token: 't0ken',
+ invite_email: 'group_invitee@example.com',
+ user: nil,
+ created_at: Time.current - 5.days
+ )
unaccepted_project_invitee = create(
- :project_member, invite_token: 't0ken',
- invite_email: 'project_invitee@example.com',
- user: nil,
- created_at: Time.current - 5.days)
+ :project_member,
+ invite_token: 't0ken',
+ invite_email: 'project_invitee@example.com',
+ user: nil,
+ created_at: Time.current - 5.days
+ )
expect { worker.perform }.to change { Member.count }.by(-2)
@@ -33,13 +37,17 @@ RSpec.describe RemoveUnacceptedMemberInvitesWorker, feature_category: :system_ac
context 'invited members still within expiration threshold' do
it 'leaves invited members', :aggregate_failures do
group_invitee = create(
- :group_member, invite_token: 't0ken',
- invite_email: 'group_invitee@example.com',
- user: nil)
+ :group_member,
+ invite_token: 't0ken',
+ invite_email: 'group_invitee@example.com',
+ user: nil
+ )
project_invitee = create(
- :project_member, invite_token: 't0ken',
- invite_email: 'project_invitee@example.com',
- user: nil)
+ :project_member,
+ invite_token: 't0ken',
+ invite_email: 'project_invitee@example.com',
+ user: nil
+ )
expect { worker.perform }.not_to change { Member.count }
@@ -56,15 +64,19 @@ RSpec.describe RemoveUnacceptedMemberInvitesWorker, feature_category: :system_ac
it 'leaves accepted members', :aggregate_failures do
user = create(:user)
accepted_group_invitee = create(
- :group_member, invite_token: 't0ken',
- invite_email: 'group_invitee@example.com',
- user: user,
- created_at: Time.current - 5.days)
+ :group_member,
+ invite_token: 't0ken',
+ invite_email: 'group_invitee@example.com',
+ user: user,
+ created_at: Time.current - 5.days
+ )
accepted_project_invitee = create(
- :project_member, invite_token: nil,
- invite_email: 'project_invitee@example.com',
- user: user,
- created_at: Time.current - 5.days)
+ :project_member,
+ invite_token: nil,
+ invite_email: 'project_invitee@example.com',
+ user: user,
+ created_at: Time.current - 5.days
+ )
expect { worker.perform }.not_to change { Member.count }
diff --git a/spec/workers/remove_unreferenced_lfs_objects_worker_spec.rb b/spec/workers/remove_unreferenced_lfs_objects_worker_spec.rb
index 56dc3511cfc..e5564834443 100644
--- a/spec/workers/remove_unreferenced_lfs_objects_worker_spec.rb
+++ b/spec/workers/remove_unreferenced_lfs_objects_worker_spec.rb
@@ -13,24 +13,16 @@ RSpec.describe RemoveUnreferencedLfsObjectsWorker, feature_category: :source_cod
let!(:referenced_lfs_object1) { create(:lfs_object, oid: '3' * 64) }
let!(:referenced_lfs_object2) { create(:lfs_object, oid: '4' * 64) }
let!(:lfs_objects_project1_1) do
- create(:lfs_objects_project,
- project: project1,
- lfs_object: referenced_lfs_object1
+ create(:lfs_objects_project, project: project1, lfs_object: referenced_lfs_object1
)
end
let!(:lfs_objects_project2_1) do
- create(:lfs_objects_project,
- project: project2,
- lfs_object: referenced_lfs_object1
- )
+ create(:lfs_objects_project, project: project2, lfs_object: referenced_lfs_object1)
end
let!(:lfs_objects_project1_2) do
- create(:lfs_objects_project,
- project: project1,
- lfs_object: referenced_lfs_object2
- )
+ create(:lfs_objects_project, project: project1, lfs_object: referenced_lfs_object2)
end
it 'removes unreferenced lfs objects' do
diff --git a/spec/workers/repository_update_remote_mirror_worker_spec.rb b/spec/workers/repository_update_remote_mirror_worker_spec.rb
index c1987658b0d..61b9441ec27 100644
--- a/spec/workers/repository_update_remote_mirror_worker_spec.rb
+++ b/spec/workers/repository_update_remote_mirror_worker_spec.rb
@@ -57,14 +57,16 @@ RSpec.describe RepositoryUpdateRemoteMirrorWorker, :clean_gitlab_redis_shared_st
end
it 'retries 3 times for the worker to finish before rescheduling' do
- expect(subject).to receive(:in_lock)
- .with("#{described_class.name}:#{remote_mirror.id}",
- retries: 3,
- ttl: remote_mirror.max_runtime,
- sleep_sec: described_class::LOCK_WAIT_TIME)
- .and_raise(Gitlab::ExclusiveLeaseHelpers::FailedToObtainLockError)
- expect(described_class).to receive(:perform_in)
- .with(remote_mirror.backoff_delay, remote_mirror.id, scheduled_time, 0)
+ expect(subject).to receive(:in_lock).with(
+ "#{described_class.name}:#{remote_mirror.id}",
+ retries: 3,
+ ttl: remote_mirror.max_runtime,
+ sleep_sec: described_class::LOCK_WAIT_TIME
+ ).and_raise(Gitlab::ExclusiveLeaseHelpers::FailedToObtainLockError)
+
+ expect(described_class)
+ .to receive(:perform_in)
+ .with(remote_mirror.backoff_delay, remote_mirror.id, scheduled_time, 0)
subject.perform(remote_mirror.id, scheduled_time)
end
diff --git a/spec/workers/run_pipeline_schedule_worker_spec.rb b/spec/workers/run_pipeline_schedule_worker_spec.rb
index 75938d3b793..d0e4de1aa98 100644
--- a/spec/workers/run_pipeline_schedule_worker_spec.rb
+++ b/spec/workers/run_pipeline_schedule_worker_spec.rb
@@ -137,9 +137,11 @@ RSpec.describe RunPipelineScheduleWorker, feature_category: :continuous_integrat
expect(Gitlab::ErrorTracking)
.to receive(:track_and_raise_for_dev_exception)
- .with(ActiveRecord::StatementInvalid,
- issue_url: 'https://gitlab.com/gitlab-org/gitlab-foss/issues/41231',
- schedule_id: pipeline_schedule.id).once
+ .with(
+ ActiveRecord::StatementInvalid,
+ issue_url: 'https://gitlab.com/gitlab-org/gitlab-foss/issues/41231',
+ schedule_id: pipeline_schedule.id
+ ).once
end
it 'increments Prometheus counter' do
diff --git a/spec/workers/update_head_pipeline_for_merge_request_worker_spec.rb b/spec/workers/update_head_pipeline_for_merge_request_worker_spec.rb
index 5eae275be36..c64a597833d 100644
--- a/spec/workers/update_head_pipeline_for_merge_request_worker_spec.rb
+++ b/spec/workers/update_head_pipeline_for_merge_request_worker_spec.rb
@@ -66,11 +66,13 @@ RSpec.describe UpdateHeadPipelineForMergeRequestWorker, feature_category: :conti
context 'when a merge request pipeline exists' do
let_it_be(:merge_request_pipeline) do
- create(:ci_pipeline,
- project: project,
- source: :merge_request_event,
- sha: latest_sha,
- merge_request: merge_request)
+ create(
+ :ci_pipeline,
+ project: project,
+ source: :merge_request_event,
+ sha: latest_sha,
+ merge_request: merge_request
+ )
end
it 'sets the merge request pipeline as the head pipeline' do
diff --git a/spec/workers/web_hook_worker_spec.rb b/spec/workers/web_hook_worker_spec.rb
index e39017c4ccf..be43b83ec0a 100644
--- a/spec/workers/web_hook_worker_spec.rb
+++ b/spec/workers/web_hook_worker_spec.rb
@@ -28,8 +28,6 @@ RSpec.describe WebHookWorker, feature_category: :integrations do
.to change { Gitlab::WebHooks::RecursionDetection::UUID.instance.request_uuid }.to(uuid)
end
- it_behaves_like 'worker with data consistency',
- described_class,
- data_consistency: :delayed
+ it_behaves_like 'worker with data consistency', described_class, data_consistency: :delayed
end
end