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
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-05-13 21:08:33 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-05-13 21:08:33 +0300
commit9adada1187b920547a57b4bb406c3e3c55436bf1 (patch)
tree6c246b5f6acd81f24071f654a41df5081d671df1
parent7eca3f56625526ffa7f263c1fef0fcea34de8ca6 (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.rubocop_todo.yml46
-rw-r--r--.rubocop_todo/rails/application_controller.yml13
-rw-r--r--.rubocop_todo/rails/content_tag.yml63
-rw-r--r--.rubocop_todo/rspec/expect_change.yml635
-rw-r--r--.rubocop_todo/style/accessor_grouping.yml78
-rw-r--r--.rubocop_todo/style/lambda.yml274
-rw-r--r--.rubocop_todo/style/redundant_regexp_escape.yml114
-rw-r--r--app/assets/javascripts/ci_variable_list/components/ci_variable_table.vue5
-rw-r--r--app/assets/javascripts/issues/list/constants.js4
-rw-r--r--app/assets/javascripts/issues/list/utils.js19
-rw-r--r--app/assets/javascripts/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_multiversion.vue11
-rw-r--r--app/assets/javascripts/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_multiversion/index.vue72
-rw-r--r--app/assets/javascripts/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_multiversion/version_select_form.vue88
-rw-r--r--app/assets/javascripts/jira_connect/subscriptions/pages/sign_in/sign_in_page.vue8
-rw-r--r--app/assets/javascripts/projects/project_new.js2
-rw-r--r--app/assets/javascripts/runner/utils.js3
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue16
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue6
-rw-r--r--app/assets/stylesheets/components/dashboard_skeleton.scss3
-rw-r--r--app/assets/stylesheets/page_bundles/jira_connect.scss5
-rw-r--r--app/assets/stylesheets/pages/notes.scss12
-rw-r--r--app/workers/container_registry/migration/enqueuer_worker.rb85
-rw-r--r--config/feature_flags/development/container_registry_migration_phase2_enqueuer_loop.yml8
-rw-r--r--config/feature_flags/development/replace_order_by_created_at_with_id.yml8
-rw-r--r--doc/api/api_resources.md1
-rw-r--r--doc/api/cluster_agent_tokens.md216
-rw-r--r--doc/api/cluster_agents.md216
-rw-r--r--doc/development/documentation/structure.md2
-rw-r--r--doc/development/experiment_guide/testing_experiments.md2
-rw-r--r--doc/development/fe_guide/development_process.md2
-rw-r--r--doc/development/go_guide/dependencies.md2
-rw-r--r--doc/development/migration_style_guide.md2
-rw-r--r--doc/development/permissions.md4
-rw-r--r--doc/development/python_guide/index.md12
-rw-r--r--doc/development/rails_update.md2
-rw-r--r--doc/development/testing_guide/end_to_end/beginners_guide.md2
-rw-r--r--doc/development/testing_guide/end_to_end/index.md6
-rw-r--r--doc/integration/elasticsearch.md2
-rw-r--r--doc/integration/saml.md2
-rw-r--r--doc/operations/incident_management/alerts.md2
-rw-r--r--doc/operations/incident_management/paging.md2
-rw-r--r--doc/security/asset_proxy.md6
-rw-r--r--doc/topics/autodevops/prepare_deployment.md2
-rw-r--r--doc/topics/autodevops/requirements.md2
-rw-r--r--doc/user/admin_area/settings/account_and_limit_settings.md2
-rw-r--r--doc/user/application_security/api_fuzzing/index.md2
-rw-r--r--doc/user/application_security/dast/checks/16.5.md2
-rw-r--r--doc/user/search/img/issue_search_by_id_v15_0.pngbin15890 -> 15461 bytes
-rw-r--r--lib/api/helpers.rb9
-rw-r--r--lib/container_registry/migration.rb4
-rw-r--r--lib/gitlab/ci/templates/Jobs/Dependency-Scanning.gitlab-ci.yml18
-rw-r--r--lib/gitlab/ci/templates/Ruby.gitlab-ci.yml2
-rw-r--r--locale/gitlab.pot27
-rw-r--r--package.json4
-rw-r--r--spec/frontend/fixtures/api_merge_requests.rb6
-rw-r--r--spec/frontend/issues/list/mock_data.js6
-rw-r--r--spec/frontend/issues/list/utils_spec.js14
-rw-r--r--spec/frontend/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_multiversion/index_spec.js83
-rw-r--r--spec/frontend/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_multiversion/version_select_form_spec.js69
-rw-r--r--spec/frontend/jira_connect/subscriptions/pages/sign_in/sign_in_page_spec.js2
-rw-r--r--spec/frontend/lib/utils/datetime_utility_spec.js2
-rw-r--r--spec/lib/api/helpers_spec.rb26
-rw-r--r--spec/lib/container_registry/migration_spec.rb14
-rw-r--r--spec/requests/api/merge_requests_spec.rb63
-rw-r--r--spec/requests/api/projects_spec.rb26
-rw-r--r--spec/support/helpers/namespaces_test_helper.rb13
-rw-r--r--spec/workers/container_registry/migration/enqueuer_worker_spec.rb738
-rw-r--r--yarn.lock192
68 files changed, 2614 insertions, 775 deletions
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
index 05b96a6b88a..64ee60d7eb8 100644
--- a/.rubocop_todo.yml
+++ b/.rubocop_todo.yml
@@ -11,13 +11,6 @@ Gitlab/PolicyRuleBoolean:
Exclude:
- 'ee/app/policies/ee/identity_provider_policy.rb'
-# Offense count: 1428
-# Cop supports --auto-correct.
-# Configuration parameters: EnforcedStyle.
-# SupportedStyles: method_call, block
-RSpec/ExpectChange:
- Enabled: false
-
# Offense count: 2352
# Cop supports --auto-correct.
# Configuration parameters: Strict, EnforcedStyle, AllowedExplicitMatchers.
@@ -36,26 +29,6 @@ RSpec/RepeatedExampleGroupBody:
Rails/ActiveRecordCallbacksOrder:
Enabled: false
-# Offense count: 10
-# Cop supports --auto-correct.
-Rails/ApplicationController:
- Exclude:
- - 'app/controllers/acme_challenges_controller.rb'
- - 'app/controllers/chaos_controller.rb'
- - 'app/controllers/health_controller.rb'
- - 'app/controllers/metrics_controller.rb'
- - 'ee/app/controllers/oauth/geo_auth_controller.rb'
- - 'ee/spec/helpers/ee/integrations_helper_spec.rb'
- - 'lib/gitlab/base_doorkeeper_controller.rb'
- - 'lib/gitlab/request_forgery_protection.rb'
- - 'spec/controllers/concerns/continue_params_spec.rb'
- - 'spec/lib/marginalia_spec.rb'
-
-# Offense count: 155
-# Cop supports --auto-correct.
-Rails/ContentTag:
- Enabled: false
-
# Offense count: 313
# Configuration parameters: Include.
# Include: db/migrate/*.rb
@@ -94,13 +67,6 @@ Rails/NegateInclude:
Rails/WhereExists:
Enabled: false
-# Offense count: 240
-# Cop supports --auto-correct.
-# Configuration parameters: EnforcedStyle.
-# SupportedStyles: separated, grouped
-Style/AccessorGrouping:
- Enabled: false
-
# Offense count: 42
# Cop supports --auto-correct.
Style/CaseLikeIf:
@@ -124,15 +90,3 @@ Style/HashAsLastArrayItem:
# Cop supports --auto-correct.
Style/KeywordParametersOrder:
Enabled: false
-
-# Offense count: 458
-# Cop supports --auto-correct.
-# Configuration parameters: EnforcedStyle.
-# SupportedStyles: line_count_dependent, lambda, literal
-Style/Lambda:
- Enabled: false
-
-# Offense count: 279
-# Cop supports --auto-correct.
-Style/RedundantRegexpEscape:
- Enabled: false
diff --git a/.rubocop_todo/rails/application_controller.yml b/.rubocop_todo/rails/application_controller.yml
new file mode 100644
index 00000000000..d53fd3411d3
--- /dev/null
+++ b/.rubocop_todo/rails/application_controller.yml
@@ -0,0 +1,13 @@
+---
+# Cop supports --auto-correct.
+Rails/ApplicationController:
+ Exclude:
+ - 'app/controllers/acme_challenges_controller.rb'
+ - 'app/controllers/chaos_controller.rb'
+ - 'app/controllers/health_controller.rb'
+ - 'app/controllers/metrics_controller.rb'
+ - 'ee/app/controllers/oauth/geo_auth_controller.rb'
+ - 'ee/spec/helpers/ee/integrations_helper_spec.rb'
+ - 'lib/gitlab/base_doorkeeper_controller.rb'
+ - 'lib/gitlab/request_forgery_protection.rb'
+ - 'spec/controllers/concerns/continue_params_spec.rb'
diff --git a/.rubocop_todo/rails/content_tag.yml b/.rubocop_todo/rails/content_tag.yml
new file mode 100644
index 00000000000..33f6dd36008
--- /dev/null
+++ b/.rubocop_todo/rails/content_tag.yml
@@ -0,0 +1,63 @@
+---
+# Cop supports --auto-correct.
+Rails/ContentTag:
+ # Offense count: 163
+ # Temporarily disabled due to too many offenses
+ Enabled: false
+ Exclude:
+ - 'app/controllers/concerns/wiki_actions.rb'
+ - 'app/helpers/appearances_helper.rb'
+ - 'app/helpers/application_helper.rb'
+ - 'app/helpers/avatars_helper.rb'
+ - 'app/helpers/blob_helper.rb'
+ - 'app/helpers/breadcrumbs_helper.rb'
+ - 'app/helpers/button_helper.rb'
+ - 'app/helpers/ci/pipelines_helper.rb'
+ - 'app/helpers/ci/runners_helper.rb'
+ - 'app/helpers/ci/status_helper.rb'
+ - 'app/helpers/clusters_helper.rb'
+ - 'app/helpers/commits_helper.rb'
+ - 'app/helpers/diff_helper.rb'
+ - 'app/helpers/dropdowns_helper.rb'
+ - 'app/helpers/emails_helper.rb'
+ - 'app/helpers/environment_helper.rb'
+ - 'app/helpers/events_helper.rb'
+ - 'app/helpers/groups_helper.rb'
+ - 'app/helpers/hooks_helper.rb'
+ - 'app/helpers/icons_helper.rb'
+ - 'app/helpers/issuables_helper.rb'
+ - 'app/helpers/issues_helper.rb'
+ - 'app/helpers/labels_helper.rb'
+ - 'app/helpers/listbox_helper.rb'
+ - 'app/helpers/markup_helper.rb'
+ - 'app/helpers/notes_helper.rb'
+ - 'app/helpers/projects_helper.rb'
+ - 'app/helpers/repository_languages_helper.rb'
+ - 'app/helpers/search_helper.rb'
+ - 'app/helpers/tab_helper.rb'
+ - 'app/helpers/timeboxes_helper.rb'
+ - 'app/helpers/todos_helper.rb'
+ - 'app/helpers/users_helper.rb'
+ - 'app/helpers/version_check_helper.rb'
+ - 'app/helpers/wiki_helper.rb'
+ - 'app/presenters/ci/pipeline_presenter.rb'
+ - 'app/presenters/merge_request_presenter.rb'
+ - 'app/presenters/project_presenter.rb'
+ - 'app/serializers/analytics/cycle_analytics/stage_entity.rb'
+ - 'app/serializers/entity_date_helper.rb'
+ - 'app/services/system_notes/base_service.rb'
+ - 'app/services/system_notes/commit_service.rb'
+ - 'ee/app/helpers/ee/button_helper.rb'
+ - 'ee/app/helpers/ee/geo_helper.rb'
+ - 'ee/app/helpers/ee/groups_helper.rb'
+ - 'ee/app/helpers/ee/issuables_helper.rb'
+ - 'ee/app/helpers/ee/lock_helper.rb'
+ - 'ee/app/helpers/ee/namespaces_helper.rb'
+ - 'ee/app/helpers/ee/search_helper.rb'
+ - 'ee/lib/gitlab/expiring_subscription_message.rb'
+ - 'lib/banzai/filter/autolink_filter.rb'
+ - 'lib/banzai/filter/gollum_tags_filter.rb'
+ - 'lib/gitlab/emoji.rb'
+ - 'lib/gitlab/form_builders/gitlab_ui_form_builder.rb'
+ - 'lib/gitlab/middleware/go.rb'
+ - 'spec/frontend/fixtures/tabs.rb'
diff --git a/.rubocop_todo/rspec/expect_change.yml b/.rubocop_todo/rspec/expect_change.yml
new file mode 100644
index 00000000000..3b4d463ad69
--- /dev/null
+++ b/.rubocop_todo/rspec/expect_change.yml
@@ -0,0 +1,635 @@
+---
+# Cop supports --auto-correct.
+RSpec/ExpectChange:
+ # Offense count: 1707
+ # Temporarily disabled due to too many offenses
+ Enabled: false
+ Exclude:
+ - 'ee/spec/controllers/admin/applications_controller_spec.rb'
+ - 'ee/spec/controllers/ee/groups_controller_spec.rb'
+ - 'ee/spec/controllers/ee/omniauth_callbacks_controller_spec.rb'
+ - 'ee/spec/controllers/ee/registrations_controller_spec.rb'
+ - 'ee/spec/controllers/groups/epic_issues_controller_spec.rb'
+ - 'ee/spec/controllers/groups/epics/notes_controller_spec.rb'
+ - 'ee/spec/controllers/groups/epics_controller_spec.rb'
+ - 'ee/spec/controllers/groups/issues_controller_spec.rb'
+ - 'ee/spec/controllers/groups/saml_providers_controller_spec.rb'
+ - 'ee/spec/controllers/groups/scim_oauth_controller_spec.rb'
+ - 'ee/spec/controllers/oauth/applications_controller_spec.rb'
+ - 'ee/spec/controllers/passwords_controller_spec.rb'
+ - 'ee/spec/controllers/profiles/keys_controller_spec.rb'
+ - 'ee/spec/controllers/projects/deploy_keys_controller_spec.rb'
+ - 'ee/spec/controllers/projects/mirrors_controller_spec.rb'
+ - 'ee/spec/controllers/projects/path_locks_controller_spec.rb'
+ - 'ee/spec/controllers/projects/protected_environments_controller_spec.rb'
+ - 'ee/spec/controllers/projects/repositories_controller_spec.rb'
+ - 'ee/spec/controllers/projects/security/vulnerabilities/notes_controller_spec.rb'
+ - 'ee/spec/controllers/projects_controller_spec.rb'
+ - 'ee/spec/controllers/registrations/groups_controller_spec.rb'
+ - 'ee/spec/controllers/registrations/groups_projects_controller_spec.rb'
+ - 'ee/spec/controllers/trials_controller_spec.rb'
+ - 'ee/spec/features/groups/group_settings_spec.rb'
+ - 'ee/spec/features/projects_spec.rb'
+ - 'ee/spec/features/users/login_spec.rb'
+ - 'ee/spec/graphql/ee/mutations/ci/runner/update_spec.rb'
+ - 'ee/spec/graphql/mutations/boards/epics/create_spec.rb'
+ - 'ee/spec/graphql/mutations/compliance_management/frameworks/update_spec.rb'
+ - 'ee/spec/graphql/mutations/dast_scanner_profiles/delete_spec.rb'
+ - 'ee/spec/graphql/mutations/dast_site_profiles/delete_spec.rb'
+ - 'ee/spec/graphql/mutations/dast_site_validations/revoke_spec.rb'
+ - 'ee/spec/helpers/paid_feature_callout_helper_spec.rb'
+ - 'ee/spec/lib/analytics/group_activity_calculator_spec.rb'
+ - 'ee/spec/lib/audit/changes_spec.rb'
+ - 'ee/spec/lib/audit/external_status_check_changes_auditor_spec.rb'
+ - 'ee/spec/lib/audit/group_push_rules_changes_auditor_spec.rb'
+ - 'ee/spec/lib/bulk_imports/projects/pipelines/issues_pipeline_spec.rb'
+ - 'ee/spec/lib/bulk_imports/projects/pipelines/push_rule_pipeline_spec.rb'
+ - 'ee/spec/lib/ee/audit/compliance_framework_changes_auditor_spec.rb'
+ - 'ee/spec/lib/ee/audit/group_changes_auditor_spec.rb'
+ - 'ee/spec/lib/ee/audit/project_changes_auditor_spec.rb'
+ - 'ee/spec/lib/ee/audit/project_ci_cd_setting_changes_auditor_spec.rb'
+ - 'ee/spec/lib/ee/audit/project_feature_changes_auditor_spec.rb'
+ - 'ee/spec/lib/ee/audit/project_setting_changes_auditor_spec.rb'
+ - 'ee/spec/lib/ee/audit/protected_branches_changes_auditor_spec.rb'
+ - 'ee/spec/lib/ee/gitlab/background_migration/create_security_setting_spec.rb'
+ - 'ee/spec/lib/ee/gitlab/background_migration/drop_invalid_remediations_spec.rb'
+ - 'ee/spec/lib/ee/gitlab/background_migration/populate_latest_pipeline_ids_spec.rb'
+ - 'ee/spec/lib/ee/gitlab/background_migration/recalculate_vulnerability_finding_signatures_for_findings_spec.rb'
+ - 'ee/spec/lib/ee/gitlab/elastic/helper_spec.rb'
+ - 'ee/spec/lib/ee/gitlab/import_export/project/tree_restorer_spec.rb'
+ - 'ee/spec/lib/ee/gitlab/import_export/repo_restorer_spec.rb'
+ - 'ee/spec/lib/ee/gitlab/scim/deprovision_service_spec.rb'
+ - 'ee/spec/lib/ee/gitlab/scim/provisioning_service_spec.rb'
+ - 'ee/spec/lib/gitlab/auth/group_saml/identity_linker_spec.rb'
+ - 'ee/spec/lib/gitlab/auth/group_saml/user_spec.rb'
+ - 'ee/spec/lib/gitlab/auth/o_auth/user_spec.rb'
+ - 'ee/spec/lib/gitlab/auth/smartcard/certificate_spec.rb'
+ - 'ee/spec/lib/gitlab/auth/smartcard/ldap_certificate_spec.rb'
+ - 'ee/spec/lib/gitlab/background_migration/migrate_requirements_to_work_items_spec.rb'
+ - 'ee/spec/lib/gitlab/mirror_spec.rb'
+ - 'ee/spec/migrations/20220411173544_cleanup_orphans_approval_project_rules_spec.rb'
+ - 'ee/spec/models/ci/bridge_spec.rb'
+ - 'ee/spec/models/ci/minutes/namespace_monthly_usage_spec.rb'
+ - 'ee/spec/models/ci/minutes/project_monthly_usage_spec.rb'
+ - 'ee/spec/models/concerns/geo/replicable_model_spec.rb'
+ - 'ee/spec/models/concerns/geo/verification_state_spec.rb'
+ - 'ee/spec/models/dast/profile_schedule_spec.rb'
+ - 'ee/spec/models/dast_site_spec.rb'
+ - 'ee/spec/models/ee/event_spec.rb'
+ - 'ee/spec/models/ee/lfs_object_spec.rb'
+ - 'ee/spec/models/ee/merge_request_diff_spec.rb'
+ - 'ee/spec/models/ee/pages_deployment_spec.rb'
+ - 'ee/spec/models/elastic/index_setting_spec.rb'
+ - 'ee/spec/models/elastic/migration_record_spec.rb'
+ - 'ee/spec/models/epic_spec.rb'
+ - 'ee/spec/models/geo/project_registry_spec.rb'
+ - 'ee/spec/models/geo/secondary_usage_data_spec.rb'
+ - 'ee/spec/models/gitlab_subscription_spec.rb'
+ - 'ee/spec/models/issue_spec.rb'
+ - 'ee/spec/models/project_import_state_spec.rb'
+ - 'ee/spec/models/project_spec.rb'
+ - 'ee/spec/models/repository_spec.rb'
+ - 'ee/spec/models/status_page/published_incident_spec.rb'
+ - 'ee/spec/models/vulnerabilities/export_spec.rb'
+ - 'ee/spec/models/vulnerabilities/statistic_spec.rb'
+ - 'ee/spec/requests/api/ci/pipelines_spec.rb'
+ - 'ee/spec/requests/api/epic_issues_spec.rb'
+ - 'ee/spec/requests/api/epics_spec.rb'
+ - 'ee/spec/requests/api/geo_spec.rb'
+ - 'ee/spec/requests/api/graphql/mutations/audit_events/external_audit_event_destinations/create_spec.rb'
+ - 'ee/spec/requests/api/graphql/mutations/audit_events/external_audit_event_destinations/destroy_spec.rb'
+ - 'ee/spec/requests/api/graphql/mutations/audit_events/external_audit_event_destinations/update_spec.rb'
+ - 'ee/spec/requests/api/graphql/mutations/boards/epics/create_spec.rb'
+ - 'ee/spec/requests/api/graphql/mutations/compliance_management/frameworks/update_spec.rb'
+ - 'ee/spec/requests/api/graphql/mutations/dast_scanner_profiles/delete_spec.rb'
+ - 'ee/spec/requests/api/graphql/mutations/dast_site_profiles/delete_spec.rb'
+ - 'ee/spec/requests/api/graphql/mutations/dast_site_tokens/create_spec.rb'
+ - 'ee/spec/requests/api/graphql/mutations/dast_site_validations/create_spec.rb'
+ - 'ee/spec/requests/api/graphql/mutations/dast_site_validations/revoke_spec.rb'
+ - 'ee/spec/requests/api/graphql/mutations/quality_management/test_cases/create_spec.rb'
+ - 'ee/spec/requests/api/graphql/mutations/requirements_management/update_requirement_spec.rb'
+ - 'ee/spec/requests/api/group_push_rule_spec.rb'
+ - 'ee/spec/requests/api/groups_spec.rb'
+ - 'ee/spec/requests/api/invitations_spec.rb'
+ - 'ee/spec/requests/api/issues_spec.rb'
+ - 'ee/spec/requests/api/members_spec.rb'
+ - 'ee/spec/requests/api/project_mirror_spec.rb'
+ - 'ee/spec/requests/api/project_push_rule_spec.rb'
+ - 'ee/spec/requests/api/projects_spec.rb'
+ - 'ee/spec/requests/api/releases_spec.rb'
+ - 'ee/spec/requests/api/repositories_spec.rb'
+ - 'ee/spec/requests/api/todos_spec.rb'
+ - 'ee/spec/requests/api/users_spec.rb'
+ - 'ee/spec/requests/ee/projects/deploy_tokens_controller_spec.rb'
+ - 'ee/spec/requests/groups_controller_spec.rb'
+ - 'ee/spec/requests/smartcard_controller_spec.rb'
+ - 'ee/spec/services/app_sec/dast/scanner_profiles/destroy_service_spec.rb'
+ - 'ee/spec/services/app_sec/dast/site_profiles/audit/update_service_spec.rb'
+ - 'ee/spec/services/app_sec/dast/site_profiles/destroy_service_spec.rb'
+ - 'ee/spec/services/app_sec/dast/site_tokens/find_or_create_service_spec.rb'
+ - 'ee/spec/services/app_sec/dast/site_validations/find_or_create_service_spec.rb'
+ - 'ee/spec/services/app_sec/dast/site_validations/revoke_service_spec.rb'
+ - 'ee/spec/services/app_sec/dast/site_validations/runner_service_spec.rb'
+ - 'ee/spec/services/application_settings/update_service_spec.rb'
+ - 'ee/spec/services/approval_rules/finalize_service_spec.rb'
+ - 'ee/spec/services/approval_rules/project_rule_destroy_service_spec.rb'
+ - 'ee/spec/services/approval_rules/update_service_spec.rb'
+ - 'ee/spec/services/audit_event_service_spec.rb'
+ - 'ee/spec/services/audit_events/user_impersonation_group_audit_event_service_spec.rb'
+ - 'ee/spec/services/auto_merge/merge_train_service_spec.rb'
+ - 'ee/spec/services/boards/epics/create_service_spec.rb'
+ - 'ee/spec/services/boards/epics/move_service_spec.rb'
+ - 'ee/spec/services/ci/destroy_pipeline_service_spec.rb'
+ - 'ee/spec/services/ci/external_pull_requests/process_github_event_service_spec.rb'
+ - 'ee/spec/services/ci/process_build_service_spec.rb'
+ - 'ee/spec/services/ci/subscribe_bridge_service_spec.rb'
+ - 'ee/spec/services/compliance_management/frameworks/create_service_spec.rb'
+ - 'ee/spec/services/compliance_management/frameworks/destroy_service_spec.rb'
+ - 'ee/spec/services/compliance_management/frameworks/update_service_spec.rb'
+ - 'ee/spec/services/deployments/approval_service_spec.rb'
+ - 'ee/spec/services/deployments/auto_rollback_service_spec.rb'
+ - 'ee/spec/services/ee/groups/deploy_tokens/create_service_spec.rb'
+ - 'ee/spec/services/ee/groups/deploy_tokens/destroy_service_spec.rb'
+ - 'ee/spec/services/ee/groups/deploy_tokens/revoke_service_spec.rb'
+ - 'ee/spec/services/ee/issuable/clone/attributes_rewriter_spec.rb'
+ - 'ee/spec/services/ee/issuable/common_system_notes_service_spec.rb'
+ - 'ee/spec/services/ee/issues/create_service_spec.rb'
+ - 'ee/spec/services/ee/issues/update_service_spec.rb'
+ - 'ee/spec/services/ee/members/create_service_spec.rb'
+ - 'ee/spec/services/ee/members/destroy_service_spec.rb'
+ - 'ee/spec/services/ee/members/invite_service_spec.rb'
+ - 'ee/spec/services/ee/members/update_service_spec.rb'
+ - 'ee/spec/services/ee/merge_requests/update_service_spec.rb'
+ - 'ee/spec/services/ee/notes/quick_actions_service_spec.rb'
+ - 'ee/spec/services/ee/projects/deploy_tokens/create_service_spec.rb'
+ - 'ee/spec/services/ee/projects/deploy_tokens/destroy_service_spec.rb'
+ - 'ee/spec/services/ee/todos/destroy/entity_leave_service_spec.rb'
+ - 'ee/spec/services/ee/users/approve_service_spec.rb'
+ - 'ee/spec/services/ee/users/block_service_spec.rb'
+ - 'ee/spec/services/ee/users/reject_service_spec.rb'
+ - 'ee/spec/services/ee/users/update_service_spec.rb'
+ - 'ee/spec/services/elastic/indexing_control_service_spec.rb'
+ - 'ee/spec/services/emails/create_service_spec.rb'
+ - 'ee/spec/services/emails/destroy_service_spec.rb'
+ - 'ee/spec/services/epic_issues/create_service_spec.rb'
+ - 'ee/spec/services/epic_issues/destroy_service_spec.rb'
+ - 'ee/spec/services/epics/close_service_spec.rb'
+ - 'ee/spec/services/epics/create_service_spec.rb'
+ - 'ee/spec/services/epics/reopen_service_spec.rb'
+ - 'ee/spec/services/epics/update_service_spec.rb'
+ - 'ee/spec/services/external_status_checks/create_service_spec.rb'
+ - 'ee/spec/services/external_status_checks/destroy_service_spec.rb'
+ - 'ee/spec/services/external_status_checks/update_service_spec.rb'
+ - 'ee/spec/services/geo/blob_download_service_spec.rb'
+ - 'ee/spec/services/geo/file_download_service_spec.rb'
+ - 'ee/spec/services/geo/metrics_update_service_spec.rb'
+ - 'ee/spec/services/geo/project_housekeeping_service_spec.rb'
+ - 'ee/spec/services/geo/registry_consistency_service_spec.rb'
+ - 'ee/spec/services/geo/repository_sync_service_spec.rb'
+ - 'ee/spec/services/group_saml/group_managed_accounts/transfer_membership_service_spec.rb'
+ - 'ee/spec/services/group_saml/identity/destroy_service_spec.rb'
+ - 'ee/spec/services/group_saml/sign_up_service_spec.rb'
+ - 'ee/spec/services/groups/mark_for_deletion_service_spec.rb'
+ - 'ee/spec/services/groups/recent_merge_requests_count_service_spec.rb'
+ - 'ee/spec/services/groups/restore_service_spec.rb'
+ - 'ee/spec/services/groups/sync_service_spec.rb'
+ - 'ee/spec/services/incident_management/oncall_rotations/edit_service_spec.rb'
+ - 'ee/spec/services/incident_management/pending_escalations/create_service_spec.rb'
+ - 'ee/spec/services/iterations/update_service_spec.rb'
+ - 'ee/spec/services/keys/create_service_spec.rb'
+ - 'ee/spec/services/lfs/lock_file_service_spec.rb'
+ - 'ee/spec/services/lfs/unlock_file_service_spec.rb'
+ - 'ee/spec/services/merge_request_approval_settings/update_service_spec.rb'
+ - 'ee/spec/services/merge_requests/update_blocks_service_spec.rb'
+ - 'ee/spec/services/namespaces/update_prevent_sharing_outside_hierarchy_service_spec.rb'
+ - 'ee/spec/services/projects/import_service_spec.rb'
+ - 'ee/spec/services/projects/mark_for_deletion_service_spec.rb'
+ - 'ee/spec/services/projects/restore_service_spec.rb'
+ - 'ee/spec/services/projects/transfer_service_spec.rb'
+ - 'ee/spec/services/projects/update_service_spec.rb'
+ - 'ee/spec/services/protected_environments/destroy_service_spec.rb'
+ - 'ee/spec/services/push_rules/create_or_update_service_spec.rb'
+ - 'ee/spec/services/requirements_management/create_requirement_service_spec.rb'
+ - 'ee/spec/services/resource_access_tokens/create_service_spec.rb'
+ - 'ee/spec/services/resource_access_tokens/revoke_service_spec.rb'
+ - 'ee/spec/services/resource_events/change_weight_service_spec.rb'
+ - 'ee/spec/services/security/ingestion/finding_map_spec.rb'
+ - 'ee/spec/services/security/ingestion/ingest_report_service_spec.rb'
+ - 'ee/spec/services/security/ingestion/tasks/ingest_identifiers_spec.rb'
+ - 'ee/spec/services/security/ingestion/tasks/ingest_vulnerabilities_spec.rb'
+ - 'ee/spec/services/security/orchestration/assign_service_spec.rb'
+ - 'ee/spec/services/security/override_uuids_service_spec.rb'
+ - 'ee/spec/services/security/store_scan_service_spec.rb'
+ - 'ee/spec/services/start_pull_mirroring_service_spec.rb'
+ - 'ee/spec/services/system_notes/epics_service_spec.rb'
+ - 'ee/spec/services/system_notes/merge_train_service_spec.rb'
+ - 'ee/spec/services/todo_service_spec.rb'
+ - 'ee/spec/services/todos/destroy/confidential_epic_service_spec.rb'
+ - 'ee/spec/services/users_ops_dashboard_projects/destroy_service_spec.rb'
+ - 'ee/spec/services/vulnerabilities/statistics/update_service_spec.rb'
+ - 'ee/spec/services/vulnerability_exports/export_service_spec.rb'
+ - 'ee/spec/services/vulnerability_feedback/create_service_spec.rb'
+ - 'ee/spec/services/vulnerability_feedback/destroy_service_spec.rb'
+ - 'ee/spec/support/shared_contexts/audit_event_not_licensed_shared_context.rb'
+ - 'ee/spec/support/shared_examples/controllers/registrations/projects_controller_shared_examples.rb'
+ - 'ee/spec/support/shared_examples/graphql/mutations/update_health_status_shared_examples.rb'
+ - 'ee/spec/support/shared_examples/models/concerns/replicable_model_with_separate_table_shared_examples.rb'
+ - 'ee/spec/support/shared_examples/models/geo_verifiable_registry_shared_examples.rb'
+ - 'ee/spec/support/shared_examples/services/group_saml/saml_provider/base_service_shared_examples.rb'
+ - 'ee/spec/support/shared_examples/services/update_issuable_health_status_shared_examples.rb'
+ - 'ee/spec/tasks/geo/git_rake_spec.rb'
+ - 'ee/spec/tasks/gitlab/elastic_rake_spec.rb'
+ - 'ee/spec/workers/elastic_remove_expired_namespace_subscriptions_from_index_cron_worker_spec.rb'
+ - 'ee/spec/workers/geo/verification_state_backfill_service_spec.rb'
+ - 'ee/spec/workers/new_epic_worker_spec.rb'
+ - 'ee/spec/workers/security/generate_scan_finding_rules_worker_spec.rb'
+ - 'ee/spec/workers/store_security_reports_worker_spec.rb'
+ - 'spec/controllers/admin/clusters_controller_spec.rb'
+ - 'spec/controllers/admin/groups_controller_spec.rb'
+ - 'spec/controllers/admin/runners_controller_spec.rb'
+ - 'spec/controllers/admin/spam_logs_controller_spec.rb'
+ - 'spec/controllers/admin/users_controller_spec.rb'
+ - 'spec/controllers/groups/clusters_controller_spec.rb'
+ - 'spec/controllers/groups/runners_controller_spec.rb'
+ - 'spec/controllers/groups_controller_spec.rb'
+ - 'spec/controllers/import/bitbucket_controller_spec.rb'
+ - 'spec/controllers/import/gitlab_controller_spec.rb'
+ - 'spec/controllers/jira_connect/events_controller_spec.rb'
+ - 'spec/controllers/ldap/omniauth_callbacks_controller_spec.rb'
+ - 'spec/controllers/omniauth_callbacks_controller_spec.rb'
+ - 'spec/controllers/profiles/gpg_keys_controller_spec.rb'
+ - 'spec/controllers/profiles/keys_controller_spec.rb'
+ - 'spec/controllers/projects/clusters_controller_spec.rb'
+ - 'spec/controllers/projects/deploy_keys_controller_spec.rb'
+ - 'spec/controllers/projects/issues_controller_spec.rb'
+ - 'spec/controllers/projects/merge_requests/creations_controller_spec.rb'
+ - 'spec/controllers/projects/merge_requests/drafts_controller_spec.rb'
+ - 'spec/controllers/projects/merge_requests_controller_spec.rb'
+ - 'spec/controllers/projects/mirrors_controller_spec.rb'
+ - 'spec/controllers/projects/notes_controller_spec.rb'
+ - 'spec/controllers/projects/pages_domains_controller_spec.rb'
+ - 'spec/controllers/projects/runners_controller_spec.rb'
+ - 'spec/controllers/projects_controller_spec.rb'
+ - 'spec/controllers/repositories/lfs_storage_controller_spec.rb'
+ - 'spec/controllers/sessions_controller_spec.rb'
+ - 'spec/controllers/snippets/notes_controller_spec.rb'
+ - 'spec/controllers/uploads_controller_spec.rb'
+ - 'spec/features/admin/users/users_spec.rb'
+ - 'spec/features/file_uploads/attachment_spec.rb'
+ - 'spec/features/file_uploads/git_lfs_spec.rb'
+ - 'spec/features/file_uploads/group_import_spec.rb'
+ - 'spec/features/file_uploads/project_import_spec.rb'
+ - 'spec/features/groups/import_export/import_file_spec.rb'
+ - 'spec/features/groups_spec.rb'
+ - 'spec/features/invites_spec.rb'
+ - 'spec/features/profiles/personal_access_tokens_spec.rb'
+ - 'spec/features/projects/import_export/import_file_spec.rb'
+ - 'spec/features/projects_spec.rb'
+ - 'spec/features/users/signup_spec.rb'
+ - 'spec/graphql/mutations/issues/set_severity_spec.rb'
+ - 'spec/graphql/mutations/releases/delete_spec.rb'
+ - 'spec/graphql/mutations/timelogs/delete_spec.rb'
+ - 'spec/initializers/active_record_locking_spec.rb'
+ - 'spec/lib/api/helpers_spec.rb'
+ - 'spec/lib/bulk_imports/projects/pipelines/project_pipeline_spec.rb'
+ - 'spec/lib/declarative_enum_spec.rb'
+ - 'spec/lib/gitlab/auth/ldap/access_spec.rb'
+ - 'spec/lib/gitlab/auth/ldap/user_spec.rb'
+ - 'spec/lib/gitlab/auth/o_auth/identity_linker_spec.rb'
+ - 'spec/lib/gitlab/auth/saml/identity_linker_spec.rb'
+ - 'spec/lib/gitlab/background_migration/add_primary_email_to_emails_if_user_confirmed_spec.rb'
+ - 'spec/lib/gitlab/background_migration/backfill_group_features_spec.rb'
+ - 'spec/lib/gitlab/background_migration/backfill_projects_with_coverage_spec.rb'
+ - 'spec/lib/gitlab/background_migration/legacy_upload_mover_spec.rb'
+ - 'spec/lib/gitlab/background_migration/migrate_u2f_webauthn_spec.rb'
+ - 'spec/lib/gitlab/background_migration/remove_duplicate_vulnerabilities_findings_spec.rb'
+ - 'spec/lib/gitlab/background_migration/remove_vulnerability_finding_links_spec.rb'
+ - 'spec/lib/gitlab/bitbucket_import/importer_spec.rb'
+ - 'spec/lib/gitlab/bitbucket_server_import/importer_spec.rb'
+ - 'spec/lib/gitlab/checks/matching_merge_request_spec.rb'
+ - 'spec/lib/gitlab/ci/ansi2json/line_spec.rb'
+ - 'spec/lib/gitlab/ci/config/external/context_spec.rb'
+ - 'spec/lib/gitlab/ci/parsers/security/common_spec.rb'
+ - 'spec/lib/gitlab/ci/pipeline/chain/create_deployments_spec.rb'
+ - 'spec/lib/gitlab/ci/pipeline/chain/ensure_environments_spec.rb'
+ - 'spec/lib/gitlab/ci/pipeline/seed/environment_spec.rb'
+ - 'spec/lib/gitlab/ci/reports/security/report_spec.rb'
+ - 'spec/lib/gitlab/ci/status/factory_spec.rb'
+ - 'spec/lib/gitlab/ci/trace/chunked_io_spec.rb'
+ - 'spec/lib/gitlab/config/entry/validatable_spec.rb'
+ - 'spec/lib/gitlab/daemon_spec.rb'
+ - 'spec/lib/gitlab/database/async_indexes/index_creator_spec.rb'
+ - 'spec/lib/gitlab/database/background_migration/batched_job_spec.rb'
+ - 'spec/lib/gitlab/database/background_migration/batched_migration_runner_spec.rb'
+ - 'spec/lib/gitlab/database/background_migration/batched_migration_spec.rb'
+ - 'spec/lib/gitlab/database/load_balancing/connection_proxy_spec.rb'
+ - 'spec/lib/gitlab/database/migration_helpers_spec.rb'
+ - 'spec/lib/gitlab/database/migrations/observers/query_statistics_spec.rb'
+ - 'spec/lib/gitlab/database/migrations/observers/total_database_size_change_spec.rb'
+ - 'spec/lib/gitlab/database/reindexing/reindex_action_spec.rb'
+ - 'spec/lib/gitlab/email/handler/service_desk_handler_spec.rb'
+ - 'spec/lib/gitlab/fogbugz_import/importer_spec.rb'
+ - 'spec/lib/gitlab/git_access_project_spec.rb'
+ - 'spec/lib/gitlab/github_import/importer/releases_importer_spec.rb'
+ - 'spec/lib/gitlab/hashed_storage/migrator_spec.rb'
+ - 'spec/lib/gitlab/import/merge_request_creator_spec.rb'
+ - 'spec/lib/gitlab/import_export/base/object_builder_spec.rb'
+ - 'spec/lib/gitlab/import_export/lfs_restorer_spec.rb'
+ - 'spec/lib/gitlab/import_export/snippet_repo_restorer_spec.rb'
+ - 'spec/lib/gitlab/issues/rebalancing/state_spec.rb'
+ - 'spec/lib/gitlab/jira_import/handle_labels_service_spec.rb'
+ - 'spec/lib/gitlab/jira_import/issue_serializer_spec.rb'
+ - 'spec/lib/gitlab/manifest_import/project_creator_spec.rb'
+ - 'spec/lib/gitlab/metrics/dashboard/importer_spec.rb'
+ - 'spec/lib/gitlab/metrics/dashboard/importers/prometheus_metrics_spec.rb'
+ - 'spec/lib/gitlab/metrics/exporter/base_exporter_spec.rb'
+ - 'spec/lib/gitlab/middleware/request_context_spec.rb'
+ - 'spec/lib/gitlab/process_memory_cache/helper_spec.rb'
+ - 'spec/lib/gitlab/process_supervisor_spec.rb'
+ - 'spec/lib/gitlab/query_limiting_spec.rb'
+ - 'spec/lib/gitlab/reference_counter_spec.rb'
+ - 'spec/lib/gitlab/slash_commands/issue_move_spec.rb'
+ - 'spec/lib/gitlab/word_diff/positions_counter_spec.rb'
+ - 'spec/migrations/20210805192450_update_trial_plans_ci_daily_pipeline_schedule_triggers_spec.rb'
+ - 'spec/migrations/20210812013042_remove_duplicate_project_authorizations_spec.rb'
+ - 'spec/migrations/20211117084814_migrate_remaining_u2f_registrations_spec.rb'
+ - 'spec/migrations/20220106111958_add_insert_or_update_vulnerability_reads_trigger_spec.rb'
+ - 'spec/migrations/20220106112043_add_update_vulnerability_reads_trigger_spec.rb'
+ - 'spec/migrations/20220124130028_dedup_runner_projects_spec.rb'
+ - 'spec/migrations/20220202105733_delete_service_template_records_spec.rb'
+ - 'spec/migrations/20220222192525_remove_null_releases_spec.rb'
+ - 'spec/migrations/backfill_cycle_analytics_aggregations_spec.rb'
+ - 'spec/migrations/cleanup_after_add_primary_email_to_emails_if_user_confirmed_spec.rb'
+ - 'spec/migrations/cleanup_after_fixing_issue_when_admin_changed_primary_email_spec.rb'
+ - 'spec/migrations/cleanup_after_fixing_regression_with_new_users_emails_spec.rb'
+ - 'spec/migrations/populate_audit_event_streaming_verification_token_spec.rb'
+ - 'spec/migrations/remove_records_without_group_from_webhooks_table_spec.rb'
+ - 'spec/migrations/remove_wiki_notes_spec.rb'
+ - 'spec/models/alert_management/alert_spec.rb'
+ - 'spec/models/analytics/cycle_analytics/aggregation_spec.rb'
+ - 'spec/models/analytics/cycle_analytics/stage_event_hash_spec.rb'
+ - 'spec/models/broadcast_message_spec.rb'
+ - 'spec/models/chat_name_spec.rb'
+ - 'spec/models/ci/bridge_spec.rb'
+ - 'spec/models/ci/build_spec.rb'
+ - 'spec/models/ci/deleted_object_spec.rb'
+ - 'spec/models/ci/namespace_mirror_spec.rb'
+ - 'spec/models/ci/pipeline_schedule_spec.rb'
+ - 'spec/models/ci/processable_spec.rb'
+ - 'spec/models/ci/project_mirror_spec.rb'
+ - 'spec/models/ci/ref_spec.rb'
+ - 'spec/models/ci/runner_spec.rb'
+ - 'spec/models/clusters/cluster_spec.rb'
+ - 'spec/models/commit_signatures/gpg_signature_spec.rb'
+ - 'spec/models/commit_signatures/x509_commit_signature_spec.rb'
+ - 'spec/models/commit_status_spec.rb'
+ - 'spec/models/concerns/atomic_internal_id_spec.rb'
+ - 'spec/models/concerns/bulk_insert_safe_spec.rb'
+ - 'spec/models/concerns/bulk_insertable_associations_spec.rb'
+ - 'spec/models/concerns/delete_with_limit_spec.rb'
+ - 'spec/models/concerns/ignorable_columns_spec.rb'
+ - 'spec/models/concerns/issuable_spec.rb'
+ - 'spec/models/concerns/resolvable_discussion_spec.rb'
+ - 'spec/models/concerns/resolvable_note_spec.rb'
+ - 'spec/models/concerns/routable_spec.rb'
+ - 'spec/models/concerns/schedulable_spec.rb'
+ - 'spec/models/container_repository_spec.rb'
+ - 'spec/models/customer_relations/issue_contact_spec.rb'
+ - 'spec/models/design_management/version_spec.rb'
+ - 'spec/models/event_spec.rb'
+ - 'spec/models/experiment_spec.rb'
+ - 'spec/models/group_spec.rb'
+ - 'spec/models/hooks/web_hook_spec.rb'
+ - 'spec/models/incident_management/timeline_event_spec.rb'
+ - 'spec/models/integrations/prometheus_spec.rb'
+ - 'spec/models/internal_id_spec.rb'
+ - 'spec/models/issue_spec.rb'
+ - 'spec/models/jira_import_state_spec.rb'
+ - 'spec/models/lfs_objects_project_spec.rb'
+ - 'spec/models/member_spec.rb'
+ - 'spec/models/merge_request_spec.rb'
+ - 'spec/models/packages/package_file_spec.rb'
+ - 'spec/models/pages_domain_spec.rb'
+ - 'spec/models/plan_spec.rb'
+ - 'spec/models/project_auto_devops_spec.rb'
+ - 'spec/models/project_import_state_spec.rb'
+ - 'spec/models/project_spec.rb'
+ - 'spec/models/projects/build_artifacts_size_refresh_spec.rb'
+ - 'spec/models/projects/ci_feature_usage_spec.rb'
+ - 'spec/models/release_spec.rb'
+ - 'spec/models/remote_mirror_spec.rb'
+ - 'spec/models/repository_spec.rb'
+ - 'spec/models/route_spec.rb'
+ - 'spec/models/sent_notification_spec.rb'
+ - 'spec/models/snippet_spec.rb'
+ - 'spec/models/upload_spec.rb'
+ - 'spec/models/user_interacted_project_spec.rb'
+ - 'spec/models/user_spec.rb'
+ - 'spec/models/user_status_spec.rb'
+ - 'spec/models/x509_certificate_spec.rb'
+ - 'spec/models/x509_issuer_spec.rb'
+ - 'spec/requests/abuse_reports_controller_spec.rb'
+ - 'spec/requests/api/broadcast_messages_spec.rb'
+ - 'spec/requests/api/ci/pipelines_spec.rb'
+ - 'spec/requests/api/ci/runner/jobs_trace_spec.rb'
+ - 'spec/requests/api/commit_statuses_spec.rb'
+ - 'spec/requests/api/deploy_keys_spec.rb'
+ - 'spec/requests/api/deploy_tokens_spec.rb'
+ - 'spec/requests/api/graphql/mutations/award_emojis/add_spec.rb'
+ - 'spec/requests/api/graphql/mutations/award_emojis/remove_spec.rb'
+ - 'spec/requests/api/graphql/mutations/award_emojis/toggle_spec.rb'
+ - 'spec/requests/api/graphql/mutations/boards/destroy_spec.rb'
+ - 'spec/requests/api/graphql/mutations/labels/create_spec.rb'
+ - 'spec/requests/api/graphql/mutations/notes/destroy_spec.rb'
+ - 'spec/requests/api/graphql/mutations/releases/delete_spec.rb'
+ - 'spec/requests/api/graphql/mutations/snippets/create_spec.rb'
+ - 'spec/requests/api/graphql/mutations/snippets/destroy_spec.rb'
+ - 'spec/requests/api/graphql/mutations/snippets/update_spec.rb'
+ - 'spec/requests/api/group_import_spec.rb'
+ - 'spec/requests/api/groups_spec.rb'
+ - 'spec/requests/api/internal/base_spec.rb'
+ - 'spec/requests/api/merge_requests_spec.rb'
+ - 'spec/requests/api/notes_spec.rb'
+ - 'spec/requests/api/project_snippets_spec.rb'
+ - 'spec/requests/api/projects_spec.rb'
+ - 'spec/requests/api/releases_spec.rb'
+ - 'spec/requests/api/snippets_spec.rb'
+ - 'spec/requests/api/system_hooks_spec.rb'
+ - 'spec/requests/api/users_spec.rb'
+ - 'spec/requests/groups/settings/access_tokens_controller_spec.rb'
+ - 'spec/requests/import/gitlab_groups_controller_spec.rb'
+ - 'spec/requests/product_analytics/collector_app_spec.rb'
+ - 'spec/requests/projects/issue_links_controller_spec.rb'
+ - 'spec/requests/projects/settings/access_tokens_controller_spec.rb'
+ - 'spec/services/alert_management/alerts/todo/create_service_spec.rb'
+ - 'spec/services/alert_management/alerts/update_service_spec.rb'
+ - 'spec/services/application_settings/update_service_spec.rb'
+ - 'spec/services/authorized_project_update/project_recalculate_per_user_service_spec.rb'
+ - 'spec/services/authorized_project_update/project_recalculate_service_spec.rb'
+ - 'spec/services/award_emojis/add_service_spec.rb'
+ - 'spec/services/award_emojis/copy_service_spec.rb'
+ - 'spec/services/award_emojis/destroy_service_spec.rb'
+ - 'spec/services/award_emojis/toggle_service_spec.rb'
+ - 'spec/services/bulk_imports/create_service_spec.rb'
+ - 'spec/services/bulk_imports/relation_export_service_spec.rb'
+ - 'spec/services/ci/create_downstream_pipeline_service_spec.rb'
+ - 'spec/services/ci/create_pipeline_service_spec.rb'
+ - 'spec/services/ci/destroy_pipeline_service_spec.rb'
+ - 'spec/services/ci/job_artifacts/update_unknown_locked_status_service_spec.rb'
+ - 'spec/services/ci/play_build_service_spec.rb'
+ - 'spec/services/ci/process_build_service_spec.rb'
+ - 'spec/services/ci/retry_job_service_spec.rb'
+ - 'spec/services/ci/retry_pipeline_service_spec.rb'
+ - 'spec/services/ci/run_scheduled_build_service_spec.rb'
+ - 'spec/services/ci/update_build_queue_service_spec.rb'
+ - 'spec/services/ci/update_build_state_service_spec.rb'
+ - 'spec/services/clusters/destroy_service_spec.rb'
+ - 'spec/services/container_expiration_policies/cleanup_service_spec.rb'
+ - 'spec/services/deployments/create_for_build_service_spec.rb'
+ - 'spec/services/deployments/update_environment_service_spec.rb'
+ - 'spec/services/design_management/copy_design_collection/copy_service_spec.rb'
+ - 'spec/services/design_management/delete_designs_service_spec.rb'
+ - 'spec/services/design_management/design_user_notes_count_service_spec.rb'
+ - 'spec/services/design_management/save_designs_service_spec.rb'
+ - 'spec/services/draft_notes/destroy_service_spec.rb'
+ - 'spec/services/draft_notes/publish_service_spec.rb'
+ - 'spec/services/emails/create_service_spec.rb'
+ - 'spec/services/error_tracking/list_projects_service_spec.rb'
+ - 'spec/services/event_create_service_spec.rb'
+ - 'spec/services/feature_flags/create_service_spec.rb'
+ - 'spec/services/feature_flags/destroy_service_spec.rb'
+ - 'spec/services/feature_flags/update_service_spec.rb'
+ - 'spec/services/git/process_ref_changes_service_spec.rb'
+ - 'spec/services/groups/create_service_spec.rb'
+ - 'spec/services/groups/import_export/import_service_spec.rb'
+ - 'spec/services/groups/transfer_service_spec.rb'
+ - 'spec/services/groups/update_service_spec.rb'
+ - 'spec/services/groups/update_statistics_service_spec.rb'
+ - 'spec/services/incident_management/timeline_events/update_service_spec.rb'
+ - 'spec/services/issuable/common_system_notes_service_spec.rb'
+ - 'spec/services/issues/close_service_spec.rb'
+ - 'spec/services/issues/create_service_spec.rb'
+ - 'spec/services/issues/move_service_spec.rb'
+ - 'spec/services/issues/reopen_service_spec.rb'
+ - 'spec/services/issues/update_service_spec.rb'
+ - 'spec/services/jira_import/start_import_service_spec.rb'
+ - 'spec/services/labels/promote_service_spec.rb'
+ - 'spec/services/lfs/lock_file_service_spec.rb'
+ - 'spec/services/merge_requests/add_spent_time_service_spec.rb'
+ - 'spec/services/merge_requests/close_service_spec.rb'
+ - 'spec/services/merge_requests/create_service_spec.rb'
+ - 'spec/services/merge_requests/ff_merge_service_spec.rb'
+ - 'spec/services/merge_requests/merge_service_spec.rb'
+ - 'spec/services/merge_requests/merge_to_ref_service_spec.rb'
+ - 'spec/services/merge_requests/post_merge_service_spec.rb'
+ - 'spec/services/merge_requests/push_options_handler_service_spec.rb'
+ - 'spec/services/merge_requests/reopen_service_spec.rb'
+ - 'spec/services/merge_requests/squash_service_spec.rb'
+ - 'spec/services/merge_requests/update_service_spec.rb'
+ - 'spec/services/milestones/destroy_service_spec.rb'
+ - 'spec/services/namespace_settings/update_service_spec.rb'
+ - 'spec/services/notes/create_service_spec.rb'
+ - 'spec/services/notes/destroy_service_spec.rb'
+ - 'spec/services/notes/quick_actions_service_spec.rb'
+ - 'spec/services/packages/helm/process_file_service_spec.rb'
+ - 'spec/services/packages/mark_package_for_destruction_service_spec.rb'
+ - 'spec/services/packages/update_package_file_service_spec.rb'
+ - 'spec/services/pages/delete_service_spec.rb'
+ - 'spec/services/pages/destroy_deployments_service_spec.rb'
+ - 'spec/services/pages_domains/retry_acme_order_service_spec.rb'
+ - 'spec/services/personal_access_tokens/last_used_service_spec.rb'
+ - 'spec/services/projects/auto_devops/disable_service_spec.rb'
+ - 'spec/services/projects/destroy_service_spec.rb'
+ - 'spec/services/projects/fetch_statistics_increment_service_spec.rb'
+ - 'spec/services/projects/hashed_storage/migration_service_spec.rb'
+ - 'spec/services/projects/hashed_storage/rollback_repository_service_spec.rb'
+ - 'spec/services/projects/hashed_storage/rollback_service_spec.rb'
+ - 'spec/services/projects/lfs_pointers/lfs_download_service_spec.rb'
+ - 'spec/services/projects/record_target_platforms_service_spec.rb'
+ - 'spec/services/projects/update_pages_service_spec.rb'
+ - 'spec/services/projects/update_service_spec.rb'
+ - 'spec/services/quick_actions/interpret_service_spec.rb'
+ - 'spec/services/releases/create_service_spec.rb'
+ - 'spec/services/releases/destroy_service_spec.rb'
+ - 'spec/services/resource_access_tokens/create_service_spec.rb'
+ - 'spec/services/serverless/associate_domain_service_spec.rb'
+ - 'spec/services/service_ping/submit_service_ping_service_spec.rb'
+ - 'spec/services/snippets/create_service_spec.rb'
+ - 'spec/services/snippets/destroy_service_spec.rb'
+ - 'spec/services/snippets/update_service_spec.rb'
+ - 'spec/services/spam/ham_service_spec.rb'
+ - 'spec/services/system_notes/issuables_service_spec.rb'
+ - 'spec/services/timelogs/delete_service_spec.rb'
+ - 'spec/services/todo_service_spec.rb'
+ - 'spec/services/todos/destroy/confidential_issue_service_spec.rb'
+ - 'spec/services/todos/destroy/design_service_spec.rb'
+ - 'spec/services/todos/destroy/entity_leave_service_spec.rb'
+ - 'spec/services/todos/destroy/group_private_service_spec.rb'
+ - 'spec/services/todos/destroy/project_private_service_spec.rb'
+ - 'spec/services/todos/destroy/unauthorized_features_service_spec.rb'
+ - 'spec/services/users/approve_service_spec.rb'
+ - 'spec/services/users/ban_service_spec.rb'
+ - 'spec/services/users/batch_status_cleaner_service_spec.rb'
+ - 'spec/services/users/block_service_spec.rb'
+ - 'spec/services/users/set_status_service_spec.rb'
+ - 'spec/services/users/unban_service_spec.rb'
+ - 'spec/services/users/update_highest_member_role_service_spec.rb'
+ - 'spec/services/users/update_service_spec.rb'
+ - 'spec/services/verify_pages_domain_service_spec.rb'
+ - 'spec/services/web_hooks/destroy_service_spec.rb'
+ - 'spec/support/services/deploy_token_shared_examples.rb'
+ - 'spec/support/services/issuable_import_csv_service_shared_examples.rb'
+ - 'spec/support/shared_contexts/email_shared_context.rb'
+ - 'spec/support/shared_examples/controllers/githubish_import_controller_shared_examples.rb'
+ - 'spec/support/shared_examples/controllers/variables_shared_examples.rb'
+ - 'spec/support/shared_examples/graphql/mutations/boards_create_shared_examples.rb'
+ - 'spec/support/shared_examples/graphql/notes_creation_shared_examples.rb'
+ - 'spec/support/shared_examples/incident_management/issuable_escalation_statuses/build_examples.rb'
+ - 'spec/support/shared_examples/loose_foreign_keys/have_loose_foreign_key.rb'
+ - 'spec/support/shared_examples/models/concerns/bulk_insert_safe_shared_examples.rb'
+ - 'spec/support/shared_examples/models/concerns/can_move_repository_storage_shared_examples.rb'
+ - 'spec/support/shared_examples/models/concerns/cron_schedulable_shared_examples.rb'
+ - 'spec/support/shared_examples/models/concerns/incident_management/escalatable_shared_examples.rb'
+ - 'spec/support/shared_examples/models/concerns/limitable_shared_examples.rb'
+ - 'spec/support/shared_examples/models/concerns/repository_storage_movable_shared_examples.rb'
+ - 'spec/support/shared_examples/models/member_shared_examples.rb'
+ - 'spec/support/shared_examples/models/packages/debian/component_file_shared_example.rb'
+ - 'spec/support/shared_examples/models/with_uploads_shared_examples.rb'
+ - 'spec/support/shared_examples/requests/access_tokens_controller_shared_examples.rb'
+ - 'spec/support/shared_examples/requests/api/graphql/mutations/destroy_list_shared_examples.rb'
+ - 'spec/support/shared_examples/requests/api/graphql/read_only_instance_shared_examples.rb'
+ - 'spec/support/shared_examples/services/common_system_notes_shared_examples.rb'
+ - 'spec/support/shared_examples/services/container_expiration_policy_shared_examples.rb'
+ - 'spec/support/shared_examples/services/container_registry_auth_service_shared_examples.rb'
+ - 'spec/support/shared_examples/services/issuable_links/create_links_shared_examples.rb'
+ - 'spec/support/shared_examples/services/merge_request_shared_examples.rb'
+ - 'spec/support/shared_examples/services/rate_limited_service_shared_examples.rb'
+ - 'spec/support/shared_examples/services/repositories/housekeeping_shared_examples.rb'
+ - 'spec/support/shared_examples/services/updating_mentions_shared_examples.rb'
+ - 'spec/support/shared_examples/services/wiki_pages/create_service_shared_examples.rb'
+ - 'spec/support/shared_examples/services/wiki_pages/destroy_service_shared_examples.rb'
+ - 'spec/support/shared_examples/services/wiki_pages/update_service_shared_examples.rb'
+ - 'spec/support/shared_examples/uploaders/object_storage_shared_examples.rb'
+ - 'spec/support/shared_examples/uploaders/upload_type_shared_examples.rb'
+ - 'spec/tasks/cache/clear/redis_spec.rb'
+ - 'spec/tooling/rspec_flaky/listener_spec.rb'
+ - 'spec/uploaders/file_uploader_spec.rb'
+ - 'spec/uploaders/records_uploads_spec.rb'
+ - 'spec/workers/destroy_pages_deployments_worker_spec.rb'
+ - 'spec/workers/environments/auto_delete_cron_worker_spec.rb'
+ - 'spec/workers/gitlab/phabricator_import/base_worker_spec.rb'
+ - 'spec/workers/group_import_worker_spec.rb'
+ - 'spec/workers/incident_management/process_alert_worker_v2_spec.rb'
+ - 'spec/workers/new_issue_worker_spec.rb'
+ - 'spec/workers/new_merge_request_worker_spec.rb'
+ - 'spec/workers/pages_domain_removal_cron_worker_spec.rb'
+ - 'spec/workers/projects/post_creation_worker_spec.rb'
+ - 'spec/workers/prune_old_events_worker_spec.rb'
+ - 'spec/workers/purge_dependency_proxy_cache_worker_spec.rb'
+ - 'spec/workers/remove_expired_group_links_worker_spec.rb'
+ - 'spec/workers/remove_expired_members_worker_spec.rb'
+ - 'spec/workers/remove_unaccepted_member_invites_worker_spec.rb'
+ - 'spec/workers/update_highest_role_worker_spec.rb'
+ - 'spec/workers/user_status_cleanup/batch_worker_spec.rb'
+ - 'spec/workers/users/create_statistics_worker_spec.rb'
+ - 'spec/workers/web_hooks/destroy_worker_spec.rb'
diff --git a/.rubocop_todo/style/accessor_grouping.yml b/.rubocop_todo/style/accessor_grouping.yml
new file mode 100644
index 00000000000..821e3398301
--- /dev/null
+++ b/.rubocop_todo/style/accessor_grouping.yml
@@ -0,0 +1,78 @@
+---
+# Cop supports --auto-correct.
+Style/AccessorGrouping:
+ # Offense count: 254
+ # Temporarily disabled due to too many offenses
+ Enabled: false
+ Exclude:
+ - 'app/finders/template_finder.rb'
+ - 'app/models/commit.rb'
+ - 'app/models/commit_range.rb'
+ - 'app/models/concerns/importable.rb'
+ - 'app/models/design_management/design_at_version.rb'
+ - 'app/models/draft_note.rb'
+ - 'app/models/integrations/chat_message/alert_message.rb'
+ - 'app/models/integrations/chat_message/base_message.rb'
+ - 'app/models/integrations/chat_message/deployment_message.rb'
+ - 'app/models/integrations/chat_message/issue_message.rb'
+ - 'app/models/integrations/chat_message/merge_message.rb'
+ - 'app/models/integrations/chat_message/note_message.rb'
+ - 'app/models/integrations/chat_message/pipeline_message.rb'
+ - 'app/models/integrations/chat_message/push_message.rb'
+ - 'app/models/integrations/chat_message/wiki_page_message.rb'
+ - 'app/models/project.rb'
+ - 'app/services/deployments/update_environment_service.rb'
+ - 'app/services/issues/clone_service.rb'
+ - 'app/services/merge_requests/bulk_remove_attention_requested_service.rb'
+ - 'app/services/note_summary.rb'
+ - 'app/services/notification_recipients/builder/default.rb'
+ - 'app/services/task_list_toggle_service.rb'
+ - 'ee/app/models/approval_wrapped_rule.rb'
+ - 'ee/app/models/integrations/chat_message/vulnerability_message.rb'
+ - 'ee/app/services/ci/pipeline_creation/drop_not_runnable_builds_service.rb'
+ - 'ee/app/services/geo/project_housekeeping_service.rb'
+ - 'ee/lib/gitlab/ci/reports/coverage_fuzzing/crash.rb'
+ - 'ee/lib/gitlab/ci/reports/coverage_fuzzing/report.rb'
+ - 'ee/lib/gitlab/ci/reports/security/locations/container_scanning.rb'
+ - 'ee/lib/gitlab/ci/reports/security/locations/coverage_fuzzing.rb'
+ - 'ee/lib/gitlab/ci/reports/security/locations/dast.rb'
+ - 'ee/lib/gitlab/ci/reports/security/locations/dependency_scanning.rb'
+ - 'lib/feature/definition.rb'
+ - 'lib/gitlab/bitbucket_server_import/importer.rb'
+ - 'lib/gitlab/ci/config/external/context.rb'
+ - 'lib/gitlab/ci/reports/security/finding.rb'
+ - 'lib/gitlab/ci/reports/security/identifier.rb'
+ - 'lib/gitlab/ci/reports/security/locations/sast.rb'
+ - 'lib/gitlab/ci/reports/security/locations/secret_detection.rb'
+ - 'lib/gitlab/ci/reports/security/scanned_resource.rb'
+ - 'lib/gitlab/ci/reports/test_suite.rb'
+ - 'lib/gitlab/ci/trace/chunked_io.rb'
+ - 'lib/gitlab/ci/variables/builder.rb'
+ - 'lib/gitlab/contributions_calendar.rb'
+ - 'lib/gitlab/database/background_migration/batch_metrics.rb'
+ - 'lib/gitlab/diff/diff_refs.rb'
+ - 'lib/gitlab/diff/formatters/base_formatter.rb'
+ - 'lib/gitlab/diff/formatters/image_formatter.rb'
+ - 'lib/gitlab/diff/formatters/text_formatter.rb'
+ - 'lib/gitlab/diff/position_tracer.rb'
+ - 'lib/gitlab/git/commit.rb'
+ - 'lib/gitlab/graphql/connection_redaction.rb'
+ - 'lib/gitlab/http_io.rb'
+ - 'lib/gitlab/import_export/group/legacy_tree_restorer.rb'
+ - 'lib/gitlab/import_export/project/tree_restorer.rb'
+ - 'lib/gitlab/merge_requests/commit_message_generator.rb'
+ - 'lib/gitlab/sidekiq_daemon/monitor.rb'
+ - 'lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job.rb'
+ - 'lib/gitlab/suggestions/file_suggestion.rb'
+ - 'lib/gitlab/tracking/event_definition.rb'
+ - 'lib/gitlab/tree_summary.rb'
+ - 'lib/gitlab/usage/metric_definition.rb'
+ - 'lib/gitlab/usage/metrics/instrumentations/base_metric.rb'
+ - 'lib/gitlab/usage/service_ping/instrumented_payload.rb'
+ - 'lib/json_web_token/token.rb'
+ - 'lib/object_storage/direct_upload.rb'
+ - 'lib/safe_zip/entry.rb'
+ - 'lib/system_check/simple_executor.rb'
+ - 'lib/uploaded_file.rb'
+ - 'qa/qa/ee/resource/geo/node.rb'
+ - 'qa/qa/ee/resource/settings/elasticsearch.rb'
diff --git a/.rubocop_todo/style/lambda.yml b/.rubocop_todo/style/lambda.yml
new file mode 100644
index 00000000000..5b898417d96
--- /dev/null
+++ b/.rubocop_todo/style/lambda.yml
@@ -0,0 +1,274 @@
+---
+# Cop supports --auto-correct.
+Style/Lambda:
+ # Offense count: 653
+ # Temporarily disabled due to too many offenses
+ Enabled: false
+ Exclude:
+ - 'app/controllers/concerns/notes_actions.rb'
+ - 'app/controllers/concerns/spammable_actions/captcha_check/rest_api_actions_support.rb'
+ - 'app/controllers/projects/issues_controller.rb'
+ - 'app/controllers/search_controller.rb'
+ - 'app/graphql/mutations/container_repositories/destroy_tags.rb'
+ - 'app/graphql/mutations/design_management/delete.rb'
+ - 'app/graphql/types/permission_types/base_permission_type.rb'
+ - 'app/models/analytics/cycle_analytics/issue_stage_event.rb'
+ - 'app/models/analytics/cycle_analytics/merge_request_stage_event.rb'
+ - 'app/models/bulk_imports/tracker.rb'
+ - 'app/models/ci/build.rb'
+ - 'app/models/ci/deleted_object.rb'
+ - 'app/models/ci/instance_variable.rb'
+ - 'app/models/ci/job_artifact.rb'
+ - 'app/models/ci/namespace_mirror.rb'
+ - 'app/models/ci/pending_build.rb'
+ - 'app/models/ci/pipeline.rb'
+ - 'app/models/ci/processable.rb'
+ - 'app/models/ci/runner.rb'
+ - 'app/models/clusters/cluster.rb'
+ - 'app/models/clusters/concerns/application_status.rb'
+ - 'app/models/commit_status.rb'
+ - 'app/models/concerns/analytics/cycle_analytics/stage_event_model.rb'
+ - 'app/models/concerns/approvable_base.rb'
+ - 'app/models/concerns/atomic_internal_id.rb'
+ - 'app/models/concerns/ci/has_status.rb'
+ - 'app/models/concerns/clusters/agents/authorization_config_scopes.rb'
+ - 'app/models/concerns/has_environment_scope.rb'
+ - 'app/models/concerns/has_wiki_page_meta_attributes.rb'
+ - 'app/models/concerns/id_in_ordered.rb'
+ - 'app/models/concerns/integrations/has_issue_tracker_fields.rb'
+ - 'app/models/concerns/issuable.rb'
+ - 'app/models/concerns/issue_resource_event.rb'
+ - 'app/models/concerns/milestoneable.rb'
+ - 'app/models/concerns/mirror_authentication.rb'
+ - 'app/models/concerns/packages/debian/component_file.rb'
+ - 'app/models/concerns/reactive_caching.rb'
+ - 'app/models/concerns/timebox.rb'
+ - 'app/models/container_repository.rb'
+ - 'app/models/custom_emoji.rb'
+ - 'app/models/deployment.rb'
+ - 'app/models/design_management/action.rb'
+ - 'app/models/design_management/design.rb'
+ - 'app/models/design_management/version.rb'
+ - 'app/models/environment.rb'
+ - 'app/models/event.rb'
+ - 'app/models/group.rb'
+ - 'app/models/group_deploy_key.rb'
+ - 'app/models/group_group_link.rb'
+ - 'app/models/hooks/web_hook.rb'
+ - 'app/models/identity.rb'
+ - 'app/models/import_failure.rb'
+ - 'app/models/integrations/zentao_tracker_data.rb'
+ - 'app/models/internal_id.rb'
+ - 'app/models/issue.rb'
+ - 'app/models/issue/metrics.rb'
+ - 'app/models/jira_connect_installation.rb'
+ - 'app/models/label.rb'
+ - 'app/models/label_link.rb'
+ - 'app/models/loose_foreign_keys/deleted_record.rb'
+ - 'app/models/member.rb'
+ - 'app/models/members/project_member.rb'
+ - 'app/models/merge_request.rb'
+ - 'app/models/merge_request/cleanup_schedule.rb'
+ - 'app/models/merge_request_diff.rb'
+ - 'app/models/merge_request_diff_file.rb'
+ - 'app/models/merge_requests_closing_issues.rb'
+ - 'app/models/milestone.rb'
+ - 'app/models/namespace.rb'
+ - 'app/models/note.rb'
+ - 'app/models/note_diff_file.rb'
+ - 'app/models/notification_setting.rb'
+ - 'app/models/onboarding_progress.rb'
+ - 'app/models/operations/feature_flags/user_list.rb'
+ - 'app/models/packages/package.rb'
+ - 'app/models/packages/package_file.rb'
+ - 'app/models/pages_domain.rb'
+ - 'app/models/product_analytics_event.rb'
+ - 'app/models/programming_language.rb'
+ - 'app/models/project.rb'
+ - 'app/models/project_feature.rb'
+ - 'app/models/project_feature_usage.rb'
+ - 'app/models/projects/topic.rb'
+ - 'app/models/prometheus_alert_event.rb'
+ - 'app/models/raw_usage_data.rb'
+ - 'app/models/redirect_route.rb'
+ - 'app/models/release.rb'
+ - 'app/models/remote_mirror.rb'
+ - 'app/models/repository_language.rb'
+ - 'app/models/snippet.rb'
+ - 'app/models/timelog.rb'
+ - 'app/models/todo.rb'
+ - 'app/models/user.rb'
+ - 'app/models/users/in_product_marketing_email.rb'
+ - 'app/serializers/ci/daily_build_group_report_result_entity.rb'
+ - 'app/serializers/group_child_entity.rb'
+ - 'app/serializers/issuable_sidebar_basic_entity.rb'
+ - 'app/serializers/merge_request_sidebar_basic_entity.rb'
+ - 'app/services/issues/referenced_merge_requests_service.rb'
+ - 'config/initializers/deprecations.rb'
+ - 'config/initializers/rspec_profiling.rb'
+ - 'config/routes/dashboard.rb'
+ - 'config/routes/group.rb'
+ - 'config/routes/issues.rb'
+ - 'db/post_migrate/20210303121224_update_gitlab_subscriptions_start_at_post_eoa.rb'
+ - 'db/post_migrate/20210513155546_backfill_nuget_temporary_packages_to_processing_status.rb'
+ - 'db/post_migrate/20210823132600_remove_duplicate_dast_site_tokens.rb'
+ - 'db/post_migrate/20220425121435_backfill_integrations_enable_ssl_verification.rb'
+ - 'ee/app/controllers/groups/analytics/productivity_analytics_controller.rb'
+ - 'ee/app/models/analytics/devops_adoption/enabled_namespace.rb'
+ - 'ee/app/models/analytics/devops_adoption/snapshot.rb'
+ - 'ee/app/models/app_sec/fuzzing/coverage/corpus.rb'
+ - 'ee/app/models/approval_merge_request_rule.rb'
+ - 'ee/app/models/boards/epic_board_position.rb'
+ - 'ee/app/models/boards/epic_user_preference.rb'
+ - 'ee/app/models/ci/minutes/project_monthly_usage.rb'
+ - 'ee/app/models/concerns/ee/protected_ref.rb'
+ - 'ee/app/models/concerns/geo/replicable_model.rb'
+ - 'ee/app/models/concerns/issue_widgets/acts_like_requirement.rb'
+ - 'ee/app/models/dast/profile.rb'
+ - 'ee/app/models/dast_site_validation.rb'
+ - 'ee/app/models/dora/daily_metrics.rb'
+ - 'ee/app/models/ee/ci/build.rb'
+ - 'ee/app/models/ee/ci/daily_build_group_report_result.rb'
+ - 'ee/app/models/ee/ci/job_artifact.rb'
+ - 'ee/app/models/ee/ci/pipeline.rb'
+ - 'ee/app/models/ee/environment.rb'
+ - 'ee/app/models/ee/epic.rb'
+ - 'ee/app/models/ee/group.rb'
+ - 'ee/app/models/ee/group_member.rb'
+ - 'ee/app/models/ee/identity.rb'
+ - 'ee/app/models/ee/issue.rb'
+ - 'ee/app/models/ee/iteration.rb'
+ - 'ee/app/models/ee/label.rb'
+ - 'ee/app/models/ee/member.rb'
+ - 'ee/app/models/ee/merge_request.rb'
+ - 'ee/app/models/ee/namespace.rb'
+ - 'ee/app/models/ee/namespace_ci_cd_setting.rb'
+ - 'ee/app/models/ee/note.rb'
+ - 'ee/app/models/ee/project.rb'
+ - 'ee/app/models/ee/user.rb'
+ - 'ee/app/models/ee/vulnerability.rb'
+ - 'ee/app/models/gitlab_subscription.rb'
+ - 'ee/app/models/incident_management/oncall_rotation.rb'
+ - 'ee/app/models/incident_management/oncall_shift.rb'
+ - 'ee/app/models/iterations/cadence.rb'
+ - 'ee/app/models/merge_request_block.rb'
+ - 'ee/app/models/merge_requests/external_status_check.rb'
+ - 'ee/app/models/merge_train.rb'
+ - 'ee/app/models/protected_environment.rb'
+ - 'ee/app/models/requirements_management/requirement.rb'
+ - 'ee/app/models/security/finding.rb'
+ - 'ee/app/models/security/orchestration_policy_configuration.rb'
+ - 'ee/app/models/security/orchestration_policy_rule_schedule.rb'
+ - 'ee/app/models/security/scan.rb'
+ - 'ee/app/models/security/training_provider.rb'
+ - 'ee/app/models/software_license_policy.rb'
+ - 'ee/app/models/vulnerabilities/feedback.rb'
+ - 'ee/app/models/vulnerabilities/finding.rb'
+ - 'ee/app/models/vulnerabilities/historical_statistic.rb'
+ - 'ee/app/models/vulnerabilities/read.rb'
+ - 'ee/app/models/vulnerabilities/scanner.rb'
+ - 'ee/app/serializers/ee/group_child_entity.rb'
+ - 'ee/lib/ee/api/entities/application_setting.rb'
+ - 'ee/lib/ee/api/entities/geo_node_status.rb'
+ - 'ee/lib/ee/api/entities/group.rb'
+ - 'ee/lib/ee/api/entities/group_push_rule.rb'
+ - 'ee/lib/ee/api/entities/project.rb'
+ - 'ee/lib/ee/api/entities/vulnerability_issue_link.rb'
+ - 'ee/lib/ee/gitlab/background_migration/populate_resolved_on_default_branch_column.rb'
+ - 'ee/lib/gem_extensions/elasticsearch/model/adapter/active_record/importing.rb'
+ - 'ee/spec/migrations/backfill_delayed_group_deletion_spec.rb'
+ - 'ee/spec/migrations/remove_schedule_and_status_null_constraints_from_pending_escalations_alert_spec.rb'
+ - 'ee/spec/services/ee/groups/autocomplete_service_spec.rb'
+ - 'ee/spec/services/ee/notes/create_service_spec.rb'
+ - 'ee/spec/support/shared_examples/lib/gitlab/middleware/maintenance_mode_gitlab_ee_instance_shared_examples.rb'
+ - 'ee/spec/support/shared_examples/lib/gitlab/middleware/read_only_gitlab_ee_instance_shared_examples.rb'
+ - 'lib/api/ci/jobs.rb'
+ - 'lib/api/ci/pipelines.rb'
+ - 'lib/api/entities/group_detail.rb'
+ - 'lib/api/entities/issue.rb'
+ - 'lib/api/entities/label.rb'
+ - 'lib/api/entities/merge_request.rb'
+ - 'lib/api/entities/project.rb'
+ - 'lib/api/entities/project_export_status.rb'
+ - 'lib/api/feature_flags_user_lists.rb'
+ - 'lib/container_registry/base_client.rb'
+ - 'lib/container_registry/client.rb'
+ - 'lib/csv_builder.rb'
+ - 'lib/event_filter.rb'
+ - 'lib/gitlab/background_migration/backfill_ci_namespace_mirrors.rb'
+ - 'lib/gitlab/background_migration/backfill_ci_project_mirrors.rb'
+ - 'lib/gitlab/background_migration/backfill_ci_queuing_tables.rb'
+ - 'lib/gitlab/background_migration/fix_projects_without_prometheus_service.rb'
+ - 'lib/gitlab/background_migration/populate_latest_pipeline_ids.rb'
+ - 'lib/gitlab/ci/config/entry/includes.rb'
+ - 'lib/gitlab/ci/config/entry/trigger.rb'
+ - 'lib/gitlab/config/entry/validatable.rb'
+ - 'lib/gitlab/database/background_migration/batched_migration.rb'
+ - 'lib/gitlab/database/background_migration_job.rb'
+ - 'lib/gitlab/database/postgres_foreign_key.rb'
+ - 'lib/gitlab/database/postgres_index.rb'
+ - 'lib/gitlab/database/postgres_partition.rb'
+ - 'lib/gitlab/database/postgres_partitioned_table.rb'
+ - 'lib/gitlab/gl_repository.rb'
+ - 'lib/gitlab/import_export/import_failure_service.rb'
+ - 'lib/gitlab/merge_requests/commit_message_generator.rb'
+ - 'lib/gitlab/seeder.rb'
+ - 'lib/gitlab/sidekiq_config/worker_matcher.rb'
+ - 'lib/gitlab/sidekiq_signals.rb'
+ - 'lib/gitlab/utils/measuring.rb'
+ - 'lib/gitlab/visibility_level.rb'
+ - 'qa/qa/fixtures/auto_devops_rack/config.ru'
+ - 'rubocop/cop/rspec/modify_sidekiq_middleware.rb'
+ - 'rubocop/cop/rspec/timecop_freeze.rb'
+ - 'rubocop/cop/rspec/timecop_travel.rb'
+ - 'spec/controllers/concerns/routable_actions_spec.rb'
+ - 'spec/deprecation_toolkit_env.rb'
+ - 'spec/factories/design_management/designs.rb'
+ - 'spec/features/projects/issues/design_management/user_views_designs_with_svg_xss_spec.rb'
+ - 'spec/graphql/resolvers/concerns/resolves_groups_spec.rb'
+ - 'spec/lib/gitlab/cross_project_access/class_methods_spec.rb'
+ - 'spec/lib/gitlab/database/consistency_spec.rb'
+ - 'spec/lib/gitlab/database/dynamic_model_helpers_spec.rb'
+ - 'spec/lib/gitlab/database/load_balancing/action_cable_callbacks_spec.rb'
+ - 'spec/lib/gitlab/database/load_balancing_spec.rb'
+ - 'spec/lib/gitlab/database/migration_helpers/restrict_gitlab_schema_spec.rb'
+ - 'spec/lib/gitlab/database/migration_helpers_spec.rb'
+ - 'spec/lib/gitlab/database/query_analyzers/gitlab_schemas_metrics_spec.rb'
+ - 'spec/lib/gitlab/graphql/tracers/timer_tracer_spec.rb'
+ - 'spec/lib/gitlab/import_export/members_mapper_spec.rb'
+ - 'spec/lib/gitlab/sidekiq_middleware/size_limiter/validator_spec.rb'
+ - 'spec/migrations/20210722150102_operations_feature_flags_correct_flexible_rollout_values_spec.rb'
+ - 'spec/migrations/20210804150320_create_base_work_item_types_spec.rb'
+ - 'spec/migrations/20210819145000_drop_temporary_columns_and_triggers_for_ci_builds_runner_session_spec.rb'
+ - 'spec/migrations/20210831203408_upsert_base_work_item_types_spec.rb'
+ - 'spec/migrations/20210902144144_drop_temporary_columns_and_triggers_for_ci_build_needs_spec.rb'
+ - 'spec/migrations/20210906100316_drop_temporary_columns_and_triggers_for_ci_build_trace_chunks_spec.rb'
+ - 'spec/migrations/20210906130643_drop_temporary_columns_and_triggers_for_taggings_spec.rb'
+ - 'spec/migrations/20210907013944_cleanup_bigint_conversion_for_ci_builds_metadata_spec.rb'
+ - 'spec/migrations/20210915022415_cleanup_bigint_conversion_for_ci_builds_spec.rb'
+ - 'spec/migrations/20210922021816_drop_int4_columns_for_ci_job_artifacts_spec.rb'
+ - 'spec/migrations/20210922025631_drop_int4_column_for_ci_sources_pipelines_spec.rb'
+ - 'spec/migrations/20210922082019_drop_int4_column_for_events_spec.rb'
+ - 'spec/migrations/20210922091402_drop_int4_column_for_push_event_payloads_spec.rb'
+ - 'spec/migrations/20211126115449_encrypt_static_objects_external_storage_auth_token_spec.rb'
+ - 'spec/migrations/20211203091642_add_index_to_projects_on_marked_for_deletion_at_spec.rb'
+ - 'spec/migrations/20220120094340_drop_position_from_security_findings_spec.rb'
+ - 'spec/migrations/20220128155814_fix_approval_rules_code_owners_rule_type_index_spec.rb'
+ - 'spec/migrations/20220305223212_add_security_training_providers_spec.rb'
+ - 'spec/migrations/20220505174658_update_index_on_alerts_to_exclude_null_fingerprints_spec.rb'
+ - 'spec/migrations/generate_customers_dot_jwt_signing_key_spec.rb'
+ - 'spec/migrations/insert_ci_daily_pipeline_schedule_triggers_plan_limits_spec.rb'
+ - 'spec/migrations/recreate_index_security_ci_builds_on_name_and_id_parser_features_spec.rb'
+ - 'spec/migrations/recreate_index_security_ci_builds_on_name_and_id_parser_with_new_features_spec.rb'
+ - 'spec/migrations/remove_schedule_and_status_from_pending_alert_escalations_spec.rb'
+ - 'spec/models/ability_spec.rb'
+ - 'spec/models/broadcast_message_spec.rb'
+ - 'spec/models/concerns/participable_spec.rb'
+ - 'spec/services/groups/autocomplete_service_spec.rb'
+ - 'spec/services/notes/create_service_spec.rb'
+ - 'spec/services/projects/autocomplete_service_spec.rb'
+ - 'spec/services/projects/lfs_pointers/lfs_download_link_list_service_spec.rb'
+ - 'spec/support/helpers/email_helpers.rb'
+ - 'spec/support/shared_examples/lib/gitlab/middleware/read_only_gitlab_instance_shared_examples.rb'
+ - 'spec/support/shared_examples/quick_actions/issuable/issuable_quick_actions_shared_examples.rb'
+ - 'spec/workers/process_commit_worker_spec.rb'
diff --git a/.rubocop_todo/style/redundant_regexp_escape.yml b/.rubocop_todo/style/redundant_regexp_escape.yml
new file mode 100644
index 00000000000..1a88f62ab64
--- /dev/null
+++ b/.rubocop_todo/style/redundant_regexp_escape.yml
@@ -0,0 +1,114 @@
+---
+# Cop supports --auto-correct.
+Style/RedundantRegexpEscape:
+ # Offense count: 325
+ # Temporarily disabled due to too many offenses
+ Enabled: false
+ Exclude:
+ - 'app/controllers/help_controller.rb'
+ - 'app/controllers/import/bitbucket_server_controller.rb'
+ - 'app/helpers/emails_helper.rb'
+ - 'app/helpers/sidekiq_helper.rb'
+ - 'app/models/commit_status.rb'
+ - 'app/models/concerns/referable.rb'
+ - 'app/models/deploy_token.rb'
+ - 'app/models/design_management/design.rb'
+ - 'app/models/integrations/chat_message/base_message.rb'
+ - 'app/models/integrations/datadog.rb'
+ - 'app/models/integrations/teamcity.rb'
+ - 'app/models/label.rb'
+ - 'app/models/license_template.rb'
+ - 'app/models/milestone.rb'
+ - 'app/models/namespace.rb'
+ - 'app/models/operations/feature_flag.rb'
+ - 'app/models/releases/link.rb'
+ - 'app/models/snippet.rb'
+ - 'app/services/metrics/dashboard/grafana_metric_embed_service.rb'
+ - 'app/uploaders/file_uploader.rb'
+ - 'config/routes/project.rb'
+ - 'config/routes/uploads.rb'
+ - 'ee/app/models/ee/epic.rb'
+ - 'ee/app/models/ee/iteration.rb'
+ - 'ee/app/models/ee/vulnerability.rb'
+ - 'ee/lib/ee/gitlab/path_regex.rb'
+ - 'ee/lib/elastic/latest/merge_request_class_proxy.rb'
+ - 'ee/lib/gitlab/geo/git_ssh_proxy.rb'
+ - 'ee/lib/gitlab/return_to_location.rb'
+ - 'ee/spec/features/read_only_spec.rb'
+ - 'ee/spec/helpers/seats_count_alert_helper_spec.rb'
+ - 'ee/spec/helpers/vulnerabilities_helper_spec.rb'
+ - 'ee/spec/lib/ee/gitlab/usage_data_counters/hll_redis_counter_spec.rb'
+ - 'ee/spec/mailers/notify_spec.rb'
+ - 'ee/spec/models/release_highlight_spec.rb'
+ - 'ee/spec/support/shared_examples/services/group_saml/saml_provider/base_service_shared_examples.rb'
+ - 'lib/api/templates.rb'
+ - 'lib/banzai/filter/autolink_filter.rb'
+ - 'lib/banzai/filter/inline_diff_filter.rb'
+ - 'lib/bulk_imports/common/pipelines/uploads_pipeline.rb'
+ - 'lib/csv_builder.rb'
+ - 'lib/gitlab/background_migration/backfill_integrations_enable_ssl_verification.rb'
+ - 'lib/gitlab/ci/pipeline/expression/lexeme/not_matches.rb'
+ - 'lib/gitlab/ci/pipeline/expression/lexeme/pattern.rb'
+ - 'lib/gitlab/diff/parser.rb'
+ - 'lib/gitlab/diff/suggestions_parser.rb'
+ - 'lib/gitlab/email/handler/create_issue_handler.rb'
+ - 'lib/gitlab/email/handler/create_merge_request_handler.rb'
+ - 'lib/gitlab/email/handler/service_desk_handler.rb'
+ - 'lib/gitlab/email/receiver.rb'
+ - 'lib/gitlab/email/reply_parser.rb'
+ - 'lib/gitlab/git/diff.rb'
+ - 'lib/gitlab/git/repository.rb'
+ - 'lib/gitlab/gitaly_client/operation_service.rb'
+ - 'lib/gitlab/incoming_email.rb'
+ - 'lib/gitlab/jira/dvcs.rb'
+ - 'lib/gitlab/path_regex.rb'
+ - 'lib/gitlab/private_commit_email.rb'
+ - 'lib/gitlab/push_options.rb'
+ - 'lib/gitlab/quick_actions/extractor.rb'
+ - 'lib/gitlab/regex.rb'
+ - 'lib/gitlab/search/abuse_detection.rb'
+ - 'lib/gitlab/task_helpers.rb'
+ - 'lib/gitlab/url_sanitizer.rb'
+ - 'lib/gitlab/utils.rb'
+ - '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/qa/specs/features/ee/browser_ui/13_secure/license_compliance_spec.rb'
+ - 'qa/qa/specs/features/ee/browser_ui/13_secure/security_reports_spec.rb'
+ - 'qa/spec/runtime/key/ecdsa_spec.rb'
+ - 'qa/spec/runtime/key/ed25519_spec.rb'
+ - 'qa/spec/runtime/key/rsa_spec.rb'
+ - 'rubocop/cop/gitlab/finder_with_find_by.rb'
+ - 'scripts/qa/testcases-check'
+ - 'scripts/setup/find-jh-branch.rb'
+ - 'spec/controllers/projects_controller_spec.rb'
+ - 'spec/features/read_only_spec.rb'
+ - 'spec/helpers/tab_helper_spec.rb'
+ - 'spec/lib/banzai/filter/references/reference_filter_spec.rb'
+ - 'spec/lib/banzai/filter/syntax_highlight_filter_spec.rb'
+ - 'spec/lib/gitlab/background_migration/backfill_work_item_type_id_for_issues_spec.rb'
+ - 'spec/lib/gitlab/ci/config_spec.rb'
+ - 'spec/lib/gitlab/ci/parsers/security/validators/schema_validator_spec.rb'
+ - 'spec/lib/gitlab/import_export/saver_spec.rb'
+ - 'spec/lib/gitlab/kubernetes/kube_client_spec.rb'
+ - 'spec/lib/gitlab/sql/pattern_spec.rb'
+ - 'spec/lib/gitlab/usage/metrics/name_suggestion_spec.rb'
+ - 'spec/lib/gitlab/usage/metrics/names_suggestions/generator_spec.rb'
+ - 'spec/lib/gitlab/usage_data_counters/hll_redis_counter_spec.rb'
+ - 'spec/models/release_highlight_spec.rb'
+ - 'spec/requests/api/graphql/mutations/merge_requests/set_draft_spec.rb'
+ - 'spec/requests/api/graphql_spec.rb'
+ - 'spec/requests/api/project_debian_distributions_spec.rb'
+ - 'spec/requests/api/repositories_spec.rb'
+ - 'spec/services/projects/download_service_spec.rb'
+ - 'spec/support/matchers/exceed_query_limit.rb'
+ - 'spec/support/shared_examples/features/wiki/file_attachments_shared_examples.rb'
+ - 'spec/support/shared_examples/mailers/notify_shared_examples.rb'
+ - 'spec/support/shared_examples/requests/api/graphql/packages/group_and_project_packages_list_shared_examples.rb'
+ - 'spec/support_specs/matchers/exceed_query_limit_helpers_spec.rb'
+ - 'spec/uploaders/personal_file_uploader_spec.rb'
+ - 'spec/views/help/index.html.haml_spec.rb'
+ - 'tooling/bin/qa/check_if_qa_only_spec_changes'
+ - 'tooling/danger/project_helper.rb'
diff --git a/app/assets/javascripts/ci_variable_list/components/ci_variable_table.vue b/app/assets/javascripts/ci_variable_list/components/ci_variable_table.vue
index 61636b389da..f078234829a 100644
--- a/app/assets/javascripts/ci_variable_list/components/ci_variable_table.vue
+++ b/app/assets/javascripts/ci_variable_list/components/ci_variable_table.vue
@@ -179,10 +179,7 @@ export default {
</p>
</template>
</gl-table>
- <div
- class="ci-variable-actions gl-display-flex"
- :class="{ 'gl-justify-content-center': isTableEmpty }"
- >
+ <div class="ci-variable-actions gl-display-flex gl-mt-5">
<gl-button
v-gl-modal-directive="$options.modalId"
class="gl-mr-3"
diff --git a/app/assets/javascripts/issues/list/constants.js b/app/assets/javascripts/issues/list/constants.js
index 4541191730a..0795df10a7c 100644
--- a/app/assets/javascripts/issues/list/constants.js
+++ b/app/assets/javascripts/issues/list/constants.js
@@ -56,6 +56,7 @@ export const ISSUE_REFERENCE = /^#\d+$/;
export const MAX_LIST_SIZE = 10;
export const PAGE_SIZE = 20;
export const PAGE_SIZE_MANUAL = 100;
+export const PARAM_ASSIGNEE_ID = 'assignee_id';
export const PARAM_PAGE_AFTER = 'page_after';
export const PARAM_PAGE_BEFORE = 'page_before';
export const PARAM_SORT = 'sort';
@@ -113,7 +114,8 @@ export const URL_PARAM = 'urlParam';
export const NORMAL_FILTER = 'normalFilter';
export const SPECIAL_FILTER = 'specialFilter';
export const ALTERNATIVE_FILTER = 'alternativeFilter';
-export const SPECIAL_FILTER_VALUES = [
+
+export const specialFilterValues = [
FILTER_NONE,
FILTER_ANY,
FILTER_CURRENT,
diff --git a/app/assets/javascripts/issues/list/utils.js b/app/assets/javascripts/issues/list/utils.js
index 2aa74dd2ea9..3ca93069628 100644
--- a/app/assets/javascripts/issues/list/utils.js
+++ b/app/assets/javascripts/issues/list/utils.js
@@ -1,5 +1,6 @@
import { createTerm } from '@gitlab/ui/src/components/base/filtered_search/filtered_search_utils';
import { isPositiveInteger } from '~/lib/utils/number_utils';
+import { getParameterByName } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
import {
FILTERED_SEARCH_TERM,
@@ -21,13 +22,14 @@ import {
NORMAL_FILTER,
PAGE_SIZE,
PAGE_SIZE_MANUAL,
+ PARAM_ASSIGNEE_ID,
POPULARITY_ASC,
POPULARITY_DESC,
PRIORITY_ASC,
PRIORITY_DESC,
RELATIVE_POSITION_ASC,
SPECIAL_FILTER,
- SPECIAL_FILTER_VALUES,
+ specialFilterValues,
TITLE_ASC,
TITLE_DESC,
TOKEN_TYPE_ASSIGNEE,
@@ -204,16 +206,19 @@ export const getFilterTokens = (locationSearch) => {
return tokens.length ? tokens : [createTerm()];
};
-const getFilterType = (data, tokenType = '') =>
- SPECIAL_FILTER_VALUES.includes(data) ||
- (tokenType === TOKEN_TYPE_ASSIGNEE && isPositiveInteger(data))
- ? SPECIAL_FILTER
- : NORMAL_FILTER;
+const getFilterType = (data, tokenType = '') => {
+ const isAssigneeIdParam =
+ tokenType === TOKEN_TYPE_ASSIGNEE &&
+ isPositiveInteger(data) &&
+ getParameterByName(PARAM_ASSIGNEE_ID) === data;
+
+ return specialFilterValues.includes(data) || isAssigneeIdParam ? SPECIAL_FILTER : NORMAL_FILTER;
+};
const wildcardTokens = [TOKEN_TYPE_ITERATION, TOKEN_TYPE_MILESTONE, TOKEN_TYPE_RELEASE];
const isWildcardValue = (tokenType, value) =>
- wildcardTokens.includes(tokenType) && SPECIAL_FILTER_VALUES.includes(value);
+ wildcardTokens.includes(tokenType) && specialFilterValues.includes(value);
const requiresUpperCaseValue = (tokenType, value) =>
tokenType === TOKEN_TYPE_TYPE || isWildcardValue(tokenType, value);
diff --git a/app/assets/javascripts/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_multiversion.vue b/app/assets/javascripts/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_multiversion.vue
deleted file mode 100644
index 1633a21ad8f..00000000000
--- a/app/assets/javascripts/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_multiversion.vue
+++ /dev/null
@@ -1,11 +0,0 @@
-<script>
-export default {
- name: 'SignInGitlabMultiversion',
-};
-</script>
-
-<template>
- <div>
- <!-- TODO -->
- </div>
-</template>
diff --git a/app/assets/javascripts/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_multiversion/index.vue b/app/assets/javascripts/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_multiversion/index.vue
new file mode 100644
index 00000000000..4f5aa4c255c
--- /dev/null
+++ b/app/assets/javascripts/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_multiversion/index.vue
@@ -0,0 +1,72 @@
+<script>
+import { GlButton } from '@gitlab/ui';
+import { s__ } from '~/locale';
+import SignInOauthButton from '../../../components/sign_in_oauth_button.vue';
+import VersionSelectForm from './version_select_form.vue';
+
+export default {
+ name: 'SignInGitlabMultiversion',
+ components: {
+ GlButton,
+ SignInOauthButton,
+ VersionSelectForm,
+ },
+ data() {
+ return {
+ gitlabBasePath: null,
+ };
+ },
+ computed: {
+ hasSelectedVersion() {
+ return this.gitlabBasePath !== null;
+ },
+ subtitle() {
+ return this.hasSelectedVersion
+ ? this.$options.i18n.signInSubtitle
+ : this.$options.i18n.versionSelectSubtitle;
+ },
+ },
+ methods: {
+ resetGitlabBasePath() {
+ this.gitlabBasePath = null;
+ },
+ onVersionSelect(gitlabBasePath) {
+ this.gitlabBasePath = gitlabBasePath;
+ },
+ onSignInError() {
+ this.$emit('error');
+ },
+ },
+ i18n: {
+ title: s__('JiraService|Welcome to GitLab for Jira'),
+ signInSubtitle: s__('JiraService|Sign in to GitLab to link namespaces.'),
+ versionSelectSubtitle: s__('JiraService|What version of GitLab are you using?'),
+ changeVersionButtonText: s__('JiraService|Change GitLab version'),
+ },
+};
+</script>
+
+<template>
+ <div>
+ <div class="gl-text-center">
+ <h2>{{ $options.i18n.title }}</h2>
+ <p data-testid="subtitle">{{ subtitle }}</p>
+ </div>
+
+ <version-select-form v-if="!hasSelectedVersion" class="gl-mt-7" @submit="onVersionSelect" />
+
+ <div v-else class="gl-text-center">
+ <sign-in-oauth-button
+ class="gl-mb-5"
+ @sign-in="$emit('sign-in-oauth', $event)"
+ @error="onSignInError"
+ />
+
+ <div>
+ <gl-button category="tertiary" variant="confirm" @click="resetGitlabBasePath">
+ {{ $options.i18n.changeVersionButtonText }}
+ </gl-button>
+ </div>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_multiversion/version_select_form.vue b/app/assets/javascripts/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_multiversion/version_select_form.vue
new file mode 100644
index 00000000000..0fa745ed7e3
--- /dev/null
+++ b/app/assets/javascripts/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_multiversion/version_select_form.vue
@@ -0,0 +1,88 @@
+<script>
+import {
+ GlForm,
+ GlFormGroup,
+ GlFormRadioGroup,
+ GlFormInput,
+ GlFormRadio,
+ GlButton,
+} from '@gitlab/ui';
+import { __, s__ } from '~/locale';
+
+const RADIO_OPTIONS = {
+ saas: 'saas',
+ selfManaged: 'selfManaged',
+};
+
+const DEFAULT_RADIO_OPTION = RADIO_OPTIONS.saas;
+const GITLAB_COM_BASE_PATH = 'https://gitlab.com';
+
+export default {
+ name: 'VersionSelectForm',
+ components: {
+ GlForm,
+ GlFormGroup,
+ GlFormRadioGroup,
+ GlFormInput,
+ GlFormRadio,
+ GlButton,
+ },
+ data() {
+ return {
+ selected: DEFAULT_RADIO_OPTION,
+ selfManagedBasePathInput: '',
+ };
+ },
+ computed: {
+ isSelfManagedSelected() {
+ return this.selected === RADIO_OPTIONS.selfManaged;
+ },
+ },
+ methods: {
+ onSubmit() {
+ const gitlabBasePath =
+ this.selected === RADIO_OPTIONS.saas ? GITLAB_COM_BASE_PATH : this.selfManagedBasePathInput;
+ this.$emit('submit', gitlabBasePath);
+ },
+ },
+ radioOptions: RADIO_OPTIONS,
+ i18n: {
+ title: s__('JiraService|Welcome to GitLab for Jira'),
+ saasRadioLabel: __('GitLab.com (SaaS)'),
+ saasRadioHelp: __('Most common'),
+ selfManagedRadioLabel: __('GitLab (self-managed)'),
+ instanceURLInputLabel: s__('JiraService|GitLab instance URL'),
+ instanceURLInputDescription: s__('JiraService|For example: https://gitlab.example.com'),
+ },
+};
+</script>
+
+<template>
+ <gl-form class="gl-max-w-62 gl-mx-auto" @submit.prevent="onSubmit">
+ <gl-form-radio-group v-model="selected" class="gl-mb-3" name="gitlab_version">
+ <gl-form-radio :value="$options.radioOptions.saas">
+ {{ $options.i18n.saasRadioLabel }}
+ <template #help>
+ {{ $options.i18n.saasRadioHelp }}
+ </template>
+ </gl-form-radio>
+ <gl-form-radio :value="$options.radioOptions.selfManaged">
+ {{ $options.i18n.selfManagedRadioLabel }}
+ </gl-form-radio>
+ </gl-form-radio-group>
+
+ <gl-form-group
+ v-if="isSelfManagedSelected"
+ class="gl-ml-6"
+ :label="$options.i18n.instanceURLInputLabel"
+ :description="$options.i18n.instanceURLInputDescription"
+ label-for="self-managed-instance-input"
+ >
+ <gl-form-input id="self-managed-instance-input" v-model="selfManagedBasePathInput" required />
+ </gl-form-group>
+
+ <div class="gl-display-flex gl-justify-content-end">
+ <gl-button variant="confirm" type="submit">{{ __('Save') }}</gl-button>
+ </div>
+ </gl-form>
+</template>
diff --git a/app/assets/javascripts/jira_connect/subscriptions/pages/sign_in/sign_in_page.vue b/app/assets/javascripts/jira_connect/subscriptions/pages/sign_in/sign_in_page.vue
index ff6b7331c57..555f095f496 100644
--- a/app/assets/javascripts/jira_connect/subscriptions/pages/sign_in/sign_in_page.vue
+++ b/app/assets/javascripts/jira_connect/subscriptions/pages/sign_in/sign_in_page.vue
@@ -1,7 +1,7 @@
<script>
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import SignInGitlabCom from './sign_in_gitlab_com.vue';
-import SignInGitlabMultiversion from './sign_in_gitlab_multiversion.vue';
+import SignInGitlabMultiversion from './sign_in_gitlab_multiversion/index.vue';
export default {
name: 'SignInPage',
@@ -21,7 +21,11 @@ export default {
};
</script>
<template>
- <sign-in-gitlab-multiversion v-if="isOauthSelfManagedEnabled" />
+ <sign-in-gitlab-multiversion
+ v-if="isOauthSelfManagedEnabled"
+ @sign-in-oauth="$emit('sign-in-oauth', $event)"
+ @error="$emit('error', $event)"
+ />
<sign-in-gitlab-com
v-else
:has-subscriptions="hasSubscriptions"
diff --git a/app/assets/javascripts/projects/project_new.js b/app/assets/javascripts/projects/project_new.js
index 3eb19a41d02..2bf13941f6f 100644
--- a/app/assets/javascripts/projects/project_new.js
+++ b/app/assets/javascripts/projects/project_new.js
@@ -1,6 +1,6 @@
import $ from 'jquery';
import { debounce } from 'lodash';
-import DEFAULT_PROJECT_TEMPLATES from 'ee_else_ce/projects/default_project_templates';
+import DEFAULT_PROJECT_TEMPLATES from 'any_else_ce/projects/default_project_templates';
import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal';
import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '../lib/utils/constants';
import { ENTER_KEY } from '../lib/utils/keys';
diff --git a/app/assets/javascripts/runner/utils.js b/app/assets/javascripts/runner/utils.js
index 1f7794720de..cb2917a92fd 100644
--- a/app/assets/javascripts/runner/utils.js
+++ b/app/assets/javascripts/runner/utils.js
@@ -1,5 +1,4 @@
import { formatNumber } from '~/locale';
-import { DEFAULT_TH_CLASSES } from '~/lib/utils/constants';
import { RUNNER_JOB_COUNT_LIMIT } from './constants';
/**
@@ -28,7 +27,7 @@ export const tableField = ({ key, label = '', thClasses = [], ...options }) => {
return {
key,
label,
- thClass: [DEFAULT_TH_CLASSES, ...thClasses],
+ thClass: thClasses,
tdAttr: {
'data-testid': `td-${key}`,
},
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue
index 87fd06ed233..4fb95fe635c 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue
@@ -785,22 +785,6 @@ export default {
>
{{ __('The latest pipeline for this merge request did not complete successfully.') }}
</div>
- <div
- v-if="
- mr.divergedCommitsCount > 0 &&
- glFeatures.updatedMrHeader &&
- !glFeatures.restructuredMrWidget
- "
- class="diverged-commits-count gl-mt-4"
- >
- <gl-sprintf :message="s__('mrWidget|The source branch is %{link} the target branch')">
- <template #link>
- <gl-link :href="mr.targetBranchPath">{{
- n__('%d commit behind', '%d commits behind', mr.divergedCommitsCount)
- }}</gl-link>
- </template>
- </gl-sprintf>
- </div>
</div>
</div>
<template v-if="shouldShowMergeControls && !glFeatures.restructuredMrWidget">
diff --git a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
index 8b4f13b4f92..88f178b4dd0 100644
--- a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
@@ -165,11 +165,9 @@ export default {
return this.mr?.codequalityReportsPath;
},
shouldRenderRelatedLinks() {
- const showDivergedCounts =
- this.mr.divergedCommitsCount > 0 && this.mr.state !== 'readyToMerge';
-
return (
- (Boolean(this.mr.relatedLinks) || showDivergedCounts) && !this.mr.isNothingToMergeState
+ (Boolean(this.mr.relatedLinks) || this.mr.divergedCommitsCount > 0) &&
+ !this.mr.isNothingToMergeState
);
},
shouldRenderSourceBranchRemovalStatus() {
diff --git a/app/assets/stylesheets/components/dashboard_skeleton.scss b/app/assets/stylesheets/components/dashboard_skeleton.scss
index 09ba89c0782..1dcaa47470b 100644
--- a/app/assets/stylesheets/components/dashboard_skeleton.scss
+++ b/app/assets/stylesheets/components/dashboard_skeleton.scss
@@ -48,8 +48,7 @@
}
}
- &-header,
- &-footer {
+ &-header {
&-failed {
background-color: $red-100;
}
diff --git a/app/assets/stylesheets/page_bundles/jira_connect.scss b/app/assets/stylesheets/page_bundles/jira_connect.scss
index 1c8fd7e2590..e898e70ce15 100644
--- a/app/assets/stylesheets/page_bundles/jira_connect.scss
+++ b/app/assets/stylesheets/page_bundles/jira_connect.scss
@@ -17,6 +17,11 @@
@import '@gitlab/ui/src/components/base/table/table';
@import '@gitlab/ui/src/components/base/tooltip/tooltip';
@import '@gitlab/ui/src/components/base/search_box_by_type/search_box_by_type';
+@import '@gitlab/ui/src/components/base/form/form_input/form_input';
+@import '@gitlab/ui/src/components/base/form/form_radio/form_radio';
+@import '@gitlab/ui/src/components/base/form/form_radio_group/form_radio_group';
+@import '@gitlab/ui/src/components/base/form/form_checkbox/form_checkbox';
+@import '@gitlab/ui/src/components/base/form/form_group/form_group';
$header-height: 40px;
diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss
index 7c5e34c0040..1949603b416 100644
--- a/app/assets/stylesheets/pages/notes.scss
+++ b/app/assets/stylesheets/pages/notes.scss
@@ -133,6 +133,11 @@ $system-note-svg-size: 16px;
display: block;
position: relative;
+ .timeline-discussion-body {
+ overflow-x: auto;
+ overflow-y: hidden;
+ }
+
.diff-content {
overflow: visible;
padding: 0;
@@ -194,13 +199,10 @@ $system-note-svg-size: 16px;
}
.note-body {
- display: flex;
- flex-direction: column;
-
+ overflow-x: auto;
+ overflow-y: hidden;
.note-text {
- overflow-x: auto;
- overflow-y: hidden;
word-wrap: break-word;
}
}
diff --git a/app/workers/container_registry/migration/enqueuer_worker.rb b/app/workers/container_registry/migration/enqueuer_worker.rb
index fd824ba6f79..c960d74367d 100644
--- a/app/workers/container_registry/migration/enqueuer_worker.rb
+++ b/app/workers/container_registry/migration/enqueuer_worker.rb
@@ -17,13 +17,7 @@ module ContainerRegistry
idempotent!
def perform
- re_enqueue = false
- try_obtain_lease do
- break unless runnable?
-
- re_enqueue = handle_aborted_migration || handle_next_migration
- end
- re_enqueue_if_capacity if re_enqueue
+ migration.enqueuer_loop? ? perform_with_loop : perform_without_loop
end
def self.enqueue_a_job
@@ -33,10 +27,36 @@ module ContainerRegistry
private
+ def perform_with_loop
+ try_obtain_lease do
+ while runnable? && Time.zone.now < loop_deadline && migration.enqueuer_loop?
+ repository_handled = handle_aborted_migration || handle_next_migration
+
+ # no repository was found: stop the loop
+ break unless repository_handled
+
+ # we're going for another iteration so we need to clear memoization
+ clear_memoization(:next_repository)
+ clear_memoization(:next_aborted_repository)
+ clear_memoization(:last_step_completed_repository)
+ end
+ end
+ end
+
+ def perform_without_loop
+ re_enqueue = false
+ try_obtain_lease do
+ break unless runnable?
+
+ re_enqueue = handle_aborted_migration || handle_next_migration
+ end
+ re_enqueue_if_capacity if re_enqueue
+ end
+
def handle_aborted_migration
return unless next_aborted_repository
- log_extra_metadata_on_done(:import_type, 'retry')
+ log_on_done(:import_type, 'retry')
log_repository(next_aborted_repository)
next_aborted_repository.retry_aborted_migration
@@ -45,15 +65,16 @@ module ContainerRegistry
rescue StandardError => e
Gitlab::ErrorTracking.log_exception(e, next_aborted_repository_id: next_aborted_repository&.id)
- true
+ migration.enqueuer_loop? ? false : true
ensure
log_repository_migration_state(next_aborted_repository)
+ log_repository_info(next_aborted_repository, import_type: 'retry')
end
def handle_next_migration
return unless next_repository
- log_extra_metadata_on_done(:import_type, 'next')
+ log_on_done(:import_type, 'next')
log_repository(next_repository)
# We return true because the repository was successfully processed (migration_state is changed)
@@ -68,6 +89,7 @@ module ContainerRegistry
false
ensure
log_repository_migration_state(next_repository)
+ log_repository_info(next_repository, import_type: 'next')
end
def tag_count_too_high?
@@ -75,8 +97,8 @@ module ContainerRegistry
return false unless next_repository.tags_count > migration.max_tags_count
next_repository.skip_import(reason: :too_many_tags)
- log_extra_metadata_on_done(:tags_count_too_high, true)
- log_extra_metadata_on_done(:max_tags_count_setting, migration.max_tags_count)
+ log_on_done(:tags_count_too_high, true)
+ log_on_done(:max_tags_count_setting, migration.max_tags_count)
true
end
@@ -155,14 +177,47 @@ module ContainerRegistry
end
def log_repository(repository)
- log_extra_metadata_on_done(:container_repository_id, repository&.id)
- log_extra_metadata_on_done(:container_repository_path, repository&.path)
+ log_on_done(:container_repository_id, repository&.id)
+ log_on_done(:container_repository_path, repository&.path)
end
def log_repository_migration_state(repository)
return unless repository
- log_extra_metadata_on_done(:container_repository_migration_state, repository.migration_state)
+ log_on_done(:container_repository_migration_state, repository.migration_state)
+ end
+
+ def log_on_done(key, value)
+ return if migration.enqueuer_loop?
+
+ log_extra_metadata_on_done(key, value)
+ end
+
+ def log_info(extras)
+ logger.info(structured_payload(extras))
+ end
+
+ def log_repository_info(repository, extras = {})
+ return unless migration.enqueuer_loop?
+ return unless repository
+
+ repository_info = {
+ container_repository_id: repository.id,
+ container_repository_path: repository.path,
+ container_repository_migration_state: repository.migration_state
+ }
+
+ if repository.import_skipped?
+ repository_info[:container_repository_migration_skipped_reason] = repository.migration_skipped_reason
+ end
+
+ log_info(extras.merge(repository_info))
+ end
+
+ def loop_deadline
+ strong_memoize(:loop_deadline) do
+ 250.seconds.from_now
+ end
end
# used by ExclusiveLeaseGuard
diff --git a/config/feature_flags/development/container_registry_migration_phase2_enqueuer_loop.yml b/config/feature_flags/development/container_registry_migration_phase2_enqueuer_loop.yml
new file mode 100644
index 00000000000..abd14090007
--- /dev/null
+++ b/config/feature_flags/development/container_registry_migration_phase2_enqueuer_loop.yml
@@ -0,0 +1,8 @@
+---
+name: container_registry_migration_phase2_enqueuer_loop
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/87168
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350543
+milestone: '15.0'
+type: development
+group: group::package
+default_enabled: false
diff --git a/config/feature_flags/development/replace_order_by_created_at_with_id.yml b/config/feature_flags/development/replace_order_by_created_at_with_id.yml
new file mode 100644
index 00000000000..c370b172cd3
--- /dev/null
+++ b/config/feature_flags/development/replace_order_by_created_at_with_id.yml
@@ -0,0 +1,8 @@
+---
+name: replace_order_by_created_at_with_id
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/86104
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/360757
+milestone: '15.0'
+type: development
+group: group::workspace
+default_enabled: false
diff --git a/doc/api/api_resources.md b/doc/api/api_resources.md
index bb7317d04eb..9408e7c25a6 100644
--- a/doc/api/api_resources.md
+++ b/doc/api/api_resources.md
@@ -26,7 +26,6 @@ The following API resources are available in the project context:
| [Access requests](access_requests.md) | `/projects/:id/access_requests` (also available for groups) |
| [Access tokens](project_access_tokens.md) | `/projects/:id/access_tokens` (also available for groups) |
| [Agents](cluster_agents.md) | `/projects/:id/cluster_agents` |
-| [Agent Tokens](cluster_agent_tokens.md) | `/projects/:id/cluster_agents/:agent_id/tokens` |
| [Award emoji](award_emoji.md) | `/projects/:id/issues/.../award_emoji`, `/projects/:id/merge_requests/.../award_emoji`, `/projects/:id/snippets/.../award_emoji` |
| [Branches](branches.md) | `/projects/:id/repository/branches/`, `/projects/:id/repository/merged_branches` |
| [Commits](commits.md) | `/projects/:id/repository/commits`, `/projects/:id/statuses` |
diff --git a/doc/api/cluster_agent_tokens.md b/doc/api/cluster_agent_tokens.md
deleted file mode 100644
index 92814e5e9af..00000000000
--- a/doc/api/cluster_agent_tokens.md
+++ /dev/null
@@ -1,216 +0,0 @@
----
-stage: Configure
-group: Configure
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
----
-
-# Agent Tokens API **(FREE)**
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/347046) in GitLab 15.0.
-
-Use the Agent Tokens API to manage tokens for the GitLab agent for Kubernetes.
-
-## List tokens for an agent
-
-Returns a list of tokens for an agent.
-
-You must have at least the Developer role to use this endpoint.
-
-```plaintext
-GET /projects/:id/cluster_agents/:agent_id/tokens
-```
-
-Supported attributes:
-
-| Attribute | Type | Required | Description |
-|------------|-------------------|-----------|------------------------------------------------------------------------------------------------------------------|
-| `id` | integer or string | yes | ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) maintained by the authenticated user. |
-| `agent_id` | integer or string | yes | ID of the agent. |
-
-Response:
-
-The response is a list of tokens with the following fields:
-
-| Attribute | Type | Description |
-|----------------------|----------------|-------------------------------------------------------------------|
-| `id` | integer | ID of the token. |
-| `name` | string | Name of the token. |
-| `description` | string or null | Description of the token. |
-| `agent_id` | integer | ID of the agent the token belongs to. |
-| `status` | string | The status of the token. Valid values are `active` and `revoked`. |
-| `created_at` | string | ISO8601 datetime when the token was created. |
-| `created_by_user_id` | string | User ID of the user who created the token. |
-
-Example request:
-
-```shell
-curl --header "Private-Token: <your_access_token>" "https://gitlab.example.com/api/v4/projects/20/cluster_agents/5/tokens"
-```
-
-Example response:
-
-```json
-[
- {
- "id": 1,
- "name": "abcd",
- "description": "Some token",
- "agent_id": 5,
- "status": "active",
- "created_at": "2022-03-25T14:12:11.497Z",
- "created_by_user_id": 1
- },
- {
- "id": 2,
- "name": "foobar",
- "description": null,
- "agent_id": 5,
- "status": "active",
- "created_at": "2022-03-25T14:12:11.497Z",
- "created_by_user_id": 1
- }
-]
-```
-
-NOTE:
-The `last_used_at` field for a token is only returned when getting a single agent token.
-
-## Get a single agent token
-
-Gets a single agent token.
-
-You must have at least the Developer role to use this endpoint.
-
-```shell
-GET /projects/:id/cluster_agents/:agent_id/tokens/:token_id
-```
-
-Supported attributes:
-
-| Attribute | Type | Required | Description |
-|------------|-------------------|----------|-------------------------------------------------------------------------------------------------------------------|
-| `id` | integer or string | yes | ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) maintained by the authenticated user. |
-| `agent_id` | integer | yes | ID of the agent. |
-| `token_id` | integer | yes | ID of the token. |
-
-Response:
-
-The response is a single token with the following fields:
-
-| Attribute | Type | Description |
-|----------------------|----------------|-------------------------------------------------------------------|
-| `id` | integer | ID of the token. |
-| `name` | string | Name of the token. |
-| `description` | string or null | Description of the token. |
-| `agent_id` | integer | ID of the agent the token belongs to. |
-| `status` | string | The status of the token. Valid values are `active` and `revoked`. |
-| `created_at` | string | ISO8601 datetime when the token was created. |
-| `created_by_user_id` | string | User ID of the user who created the token. |
-| `last_used_at` | string or null | ISO8601 datetime when the token was last used. |
-
-Example request:
-
-```shell
-curl --header "Private-Token: <your_access_token>" "https://gitlab.example.com/api/v4/projects/20/cluster_agents/5/token/1"
-```
-
-Example response:
-
-```json
-{
- "id": 1,
- "name": "abcd",
- "description": "Some token",
- "agent_id": 5,
- "status": "active",
- "created_at": "2022-03-25T14:12:11.497Z",
- "created_by_user_id": 1,
- "last_used_at": null
-}
-```
-
-## Create an agent token
-
-Creates a new token for an agent.
-
-You must have at least the Maintainer role to use this endpoint.
-
-```shell
-POST /projects/:id/cluster_agents/:agent_id/tokens
-```
-
-Supported attributes:
-
-| Attribute | Type | Required | Description |
-|---------------|-------------------|----------|------------------------------------------------------------------------------------------------------------------|
-| `id` | integer or string | yes | ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) maintained by the authenticated user. |
-| `agent_id` | integer | yes | ID of the agent. |
-| `name` | string | yes | Name for the token. |
-| `description` | string | no | Description for the token. |
-
-Response:
-
-The response is the new token with the following fields:
-
-| Attribute | Type | Description |
-|----------------------|----------------|-------------------------------------------------------------------|
-| `id` | integer | ID of the token. |
-| `name` | string | Name of the token. |
-| `description` | string or null | Description of the token. |
-| `agent_id` | integer | ID of the agent the token belongs to. |
-| `status` | string | The status of the token. Valid values are `active` and `revoked`. |
-| `created_at` | string | ISO8601 datetime when the token was created. |
-| `created_by_user_id` | string | User ID of the user who created the token. |
-| `last_used_at` | string or null | ISO8601 datetime when the token was last used. |
-| `token` | string | The secret token value. |
-
-NOTE:
-The `token` is only returned in the response of the `POST` endpoint and cannot be retrieved afterwards.
-
-Example request:
-
-```shell
-curl --header "Private-Token: <your_access_token>" "https://gitlab.example.com/api/v4/projects/20/cluster_agents/5/tokens" \
- -H "Content-Type:application/json" \
- -X POST --data '{"name":"some-token"}'
-```
-
-Example response:
-
-```json
-{
- "id": 1,
- "name": "abcd",
- "description": "Some token",
- "agent_id": 5,
- "status": "active",
- "created_at": "2022-03-25T14:12:11.497Z",
- "created_by_user_id": 1,
- "last_used_at": null,
- "token": "qeY8UVRisx9y3Loxo1scLxFuRxYcgeX3sxsdrpP_fR3Loq4xyg"
-}
-```
-
-## Revoke an agent token
-
-Revokes an agent token.
-
-You must have at least the Maintainer role to use this endpoint.
-
-```plaintext
-DELETE /projects/:id/cluster_agents/:agent_id/tokens/:token_id
-```
-
-Supported attributes:
-
-| Attribute | Type | Required | Description |
-|------------|-------------------|----------|---------------------------------------------------------------------------------------------------------------- -|
-| `id` | integer or string | yes | ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) maintained by the authenticated user. |
-| `agent_id` | integer | yes | ID of the agent. |
-| `token_id` | integer | yes | ID of the token. |
-
-Example request:
-
-```shell
-curl --request DELETE --header "Private-Token: <your_access_token>" "https://gitlab.example.com/api/v4/projects/20/cluster_agents/5/tokens/1
-```
diff --git a/doc/api/cluster_agents.md b/doc/api/cluster_agents.md
index 37cc4a24342..1c2a3b52761 100644
--- a/doc/api/cluster_agents.md
+++ b/doc/api/cluster_agents.md
@@ -6,7 +6,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Agents API **(FREE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/83270) in GitLab 14.10.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/83270) in GitLab 14.10.
+> - Agent Tokens API [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/347046) in GitLab 15.0.
Use the Agents API to work with the GitLab agent for Kubernetes.
@@ -236,3 +237,216 @@ Example request:
```shell
curl --request DELETE --header "Private-Token: <your_access_token>" "https://gitlab.example.com/api/v4/projects/20/cluster_agents/1
```
+
+## List tokens for an agent
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/347046) in GitLab 15.0.
+
+Returns a list of tokens for an agent.
+
+You must have at least the Developer role to use this endpoint.
+
+```plaintext
+GET /projects/:id/cluster_agents/:agent_id/tokens
+```
+
+Supported attributes:
+
+| Attribute | Type | Required | Description |
+|------------|-------------------|-----------|------------------------------------------------------------------------------------------------------------------|
+| `id` | integer or string | yes | ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) maintained by the authenticated user. |
+| `agent_id` | integer or string | yes | ID of the agent. |
+
+Response:
+
+The response is a list of tokens with the following fields:
+
+| Attribute | Type | Description |
+|----------------------|----------------|-------------------------------------------------------------------|
+| `id` | integer | ID of the token. |
+| `name` | string | Name of the token. |
+| `description` | string or null | Description of the token. |
+| `agent_id` | integer | ID of the agent the token belongs to. |
+| `status` | string | The status of the token. Valid values are `active` and `revoked`. |
+| `created_at` | string | ISO8601 datetime when the token was created. |
+| `created_by_user_id` | string | User ID of the user who created the token. |
+
+Example request:
+
+```shell
+curl --header "Private-Token: <your_access_token>" "https://gitlab.example.com/api/v4/projects/20/cluster_agents/5/tokens"
+```
+
+Example response:
+
+```json
+[
+ {
+ "id": 1,
+ "name": "abcd",
+ "description": "Some token",
+ "agent_id": 5,
+ "status": "active",
+ "created_at": "2022-03-25T14:12:11.497Z",
+ "created_by_user_id": 1
+ },
+ {
+ "id": 2,
+ "name": "foobar",
+ "description": null,
+ "agent_id": 5,
+ "status": "active",
+ "created_at": "2022-03-25T14:12:11.497Z",
+ "created_by_user_id": 1
+ }
+]
+```
+
+NOTE:
+The `last_used_at` field for a token is only returned when getting a single agent token.
+
+## Get a single agent token
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/347046) in GitLab 15.0.
+
+Gets a single agent token.
+
+You must have at least the Developer role to use this endpoint.
+
+```shell
+GET /projects/:id/cluster_agents/:agent_id/tokens/:token_id
+```
+
+Supported attributes:
+
+| Attribute | Type | Required | Description |
+|------------|-------------------|----------|-------------------------------------------------------------------------------------------------------------------|
+| `id` | integer or string | yes | ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) maintained by the authenticated user. |
+| `agent_id` | integer | yes | ID of the agent. |
+| `token_id` | integer | yes | ID of the token. |
+
+Response:
+
+The response is a single token with the following fields:
+
+| Attribute | Type | Description |
+|----------------------|----------------|-------------------------------------------------------------------|
+| `id` | integer | ID of the token. |
+| `name` | string | Name of the token. |
+| `description` | string or null | Description of the token. |
+| `agent_id` | integer | ID of the agent the token belongs to. |
+| `status` | string | The status of the token. Valid values are `active` and `revoked`. |
+| `created_at` | string | ISO8601 datetime when the token was created. |
+| `created_by_user_id` | string | User ID of the user who created the token. |
+| `last_used_at` | string or null | ISO8601 datetime when the token was last used. |
+
+Example request:
+
+```shell
+curl --header "Private-Token: <your_access_token>" "https://gitlab.example.com/api/v4/projects/20/cluster_agents/5/token/1"
+```
+
+Example response:
+
+```json
+{
+ "id": 1,
+ "name": "abcd",
+ "description": "Some token",
+ "agent_id": 5,
+ "status": "active",
+ "created_at": "2022-03-25T14:12:11.497Z",
+ "created_by_user_id": 1,
+ "last_used_at": null
+}
+```
+
+## Create an agent token
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/347046) in GitLab 15.0.
+
+Creates a new token for an agent.
+
+You must have at least the Maintainer role to use this endpoint.
+
+```shell
+POST /projects/:id/cluster_agents/:agent_id/tokens
+```
+
+Supported attributes:
+
+| Attribute | Type | Required | Description |
+|---------------|-------------------|----------|------------------------------------------------------------------------------------------------------------------|
+| `id` | integer or string | yes | ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) maintained by the authenticated user. |
+| `agent_id` | integer | yes | ID of the agent. |
+| `name` | string | yes | Name for the token. |
+| `description` | string | no | Description for the token. |
+
+Response:
+
+The response is the new token with the following fields:
+
+| Attribute | Type | Description |
+|----------------------|----------------|-------------------------------------------------------------------|
+| `id` | integer | ID of the token. |
+| `name` | string | Name of the token. |
+| `description` | string or null | Description of the token. |
+| `agent_id` | integer | ID of the agent the token belongs to. |
+| `status` | string | The status of the token. Valid values are `active` and `revoked`. |
+| `created_at` | string | ISO8601 datetime when the token was created. |
+| `created_by_user_id` | string | User ID of the user who created the token. |
+| `last_used_at` | string or null | ISO8601 datetime when the token was last used. |
+| `token` | string | The secret token value. |
+
+NOTE:
+The `token` is only returned in the response of the `POST` endpoint and cannot be retrieved afterwards.
+
+Example request:
+
+```shell
+curl --header "Private-Token: <your_access_token>" "https://gitlab.example.com/api/v4/projects/20/cluster_agents/5/tokens" \
+ -H "Content-Type:application/json" \
+ -X POST --data '{"name":"some-token"}'
+```
+
+Example response:
+
+```json
+{
+ "id": 1,
+ "name": "abcd",
+ "description": "Some token",
+ "agent_id": 5,
+ "status": "active",
+ "created_at": "2022-03-25T14:12:11.497Z",
+ "created_by_user_id": 1,
+ "last_used_at": null,
+ "token": "qeY8UVRisx9y3Loxo1scLxFuRxYcgeX3sxsdrpP_fR3Loq4xyg"
+}
+```
+
+## Revoke an agent token
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/347046) in GitLab 15.0.
+
+Revokes an agent token.
+
+You must have at least the Maintainer role to use this endpoint.
+
+```plaintext
+DELETE /projects/:id/cluster_agents/:agent_id/tokens/:token_id
+```
+
+Supported attributes:
+
+| Attribute | Type | Required | Description |
+|------------|-------------------|----------|---------------------------------------------------------------------------------------------------------------- -|
+| `id` | integer or string | yes | ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) maintained by the authenticated user. |
+| `agent_id` | integer | yes | ID of the agent. |
+| `token_id` | integer | yes | ID of the token. |
+
+Example request:
+
+```shell
+curl --request DELETE --header "Private-Token: <your_access_token>" "https://gitlab.example.com/api/v4/projects/20/cluster_agents/5/tokens/1
+```
diff --git a/doc/development/documentation/structure.md b/doc/development/documentation/structure.md
index bba8e99260d..329fd279b99 100644
--- a/doc/development/documentation/structure.md
+++ b/doc/development/documentation/structure.md
@@ -336,7 +336,7 @@ Consider the following guidelines when offering examples:
the reader to go directly to the good part. Consider offering an explanation
(for example, a comment, or a link to a resource) on why something is bad
practice.
-- Better and best cases can be considered part of the good case(s) code block.
+- Better and best cases can be considered part of the good cases' code block.
In the same code block, precede each with comments: `# Better` and `# Best`.
Although the bad-then-good approach is acceptable for the GitLab development
diff --git a/doc/development/experiment_guide/testing_experiments.md b/doc/development/experiment_guide/testing_experiments.md
index c51c3c7cb11..08ff91a3deb 100644
--- a/doc/development/experiment_guide/testing_experiments.md
+++ b/doc/development/experiment_guide/testing_experiments.md
@@ -127,7 +127,7 @@ describe('when my_experiment is enabled', () => {
```
NOTE:
-This method of stubbing in Jest specs will not automatically un-stub itself at the end of the test. We merge our stubbed experiment in with all the other global data in `window.gl`. If you need to remove the stubbed experiment(s) after your test or ensure a clean global object before your test, you'll need to manage the global object directly yourself:
+This method of stubbing in Jest specs will not automatically un-stub itself at the end of the test. We merge our stubbed experiment in with all the other global data in `window.gl`. If you need to remove the stubbed experiments after your test or ensure a clean global object before your test, you'll need to manage the global object directly yourself:
```javascript
describe('tests that care about global state', () => {
diff --git a/doc/development/fe_guide/development_process.md b/doc/development/fe_guide/development_process.md
index 9921b851344..b4893fd4ef9 100644
--- a/doc/development/fe_guide/development_process.md
+++ b/doc/development/fe_guide/development_process.md
@@ -103,7 +103,7 @@ With the purpose of being [respectful of others' time](https://about.gitlab.com/
- Before assigning to a maintainer, assign to a reviewer.
- If you assigned a merge request or pinged someone directly, be patient because we work in different timezones and asynchronously. Unless the merge request is urgent (like fixing a broken default branch), please don't DM or reassign the merge request before waiting for a 24-hour window.
- If you have a question regarding your merge request/issue, make it on the merge request/issue. When we DM each other, we no longer have a SSOT and [no one else is able to contribute](https://about.gitlab.com/handbook/values/#public-by-default).
-- When you have a big **Draft** merge request with many changes, you're advised to get the review started before adding/removing significant code. Make sure it is assigned well before the release cut-off, as the reviewer(s)/maintainer(s) would always prioritize reviewing finished MRs before the **Draft** ones.
+- When you have a big **Draft** merge request with many changes, you're advised to get the review started before adding/removing significant code. Make sure it is assigned well before the release cut-off, as the reviewers/maintainers would always prioritize reviewing finished MRs before the **Draft** ones.
- Make sure to remove the `Draft:` title before the last round of review.
### Share your work early
diff --git a/doc/development/go_guide/dependencies.md b/doc/development/go_guide/dependencies.md
index 8aa8f286edc..0c2ce4f2b48 100644
--- a/doc/development/go_guide/dependencies.md
+++ b/doc/development/go_guide/dependencies.md
@@ -102,7 +102,7 @@ malicious party without causing build failures.
Go 1.12+ can be configured to use a checksum database. If configured to do so,
when Go fetches a dependency and there is no corresponding entry in `go.sum`, Go
-queries the configured checksum database(s) for the checksum of the
+queries the configured checksum databases for the checksum of the
dependency instead of calculating it from the downloaded dependency. If the
dependency cannot be found in the checksum database, the build fails. If the
downloaded dependency's checksum does not match the result from the checksum
diff --git a/doc/development/migration_style_guide.md b/doc/development/migration_style_guide.md
index 39fb4510004..aebecd90574 100644
--- a/doc/development/migration_style_guide.md
+++ b/doc/development/migration_style_guide.md
@@ -625,7 +625,7 @@ end
```
You must explicitly name indexes that are created with more complex
-definitions beyond table name, column name(s) and uniqueness constraint.
+definitions beyond table name, column names, and uniqueness constraint.
Consult the [Adding Database Indexes](adding_database_indexes.md#requirements-for-naming-indexes)
guide for more details.
diff --git a/doc/development/permissions.md b/doc/development/permissions.md
index 47aebc2f4d2..f3818e92fec 100644
--- a/doc/development/permissions.md
+++ b/doc/development/permissions.md
@@ -86,10 +86,10 @@ module):
- Maintainer (`40`)
- Owner (`50`)
-If a user is the member of both a project and the project parent group(s), the
+If a user is the member of both a project and the project parent groups, the
higher permission is taken into account for the project.
-If a user is the member of a project, but not the parent group(s), they
+If a user is the member of a project, but not the parent groups, they
can still view the groups and their entities (like epics).
Project membership (where the group membership is already taken into account)
diff --git a/doc/development/python_guide/index.md b/doc/development/python_guide/index.md
index fe5492c3bd8..77dd328b513 100644
--- a/doc/development/python_guide/index.md
+++ b/doc/development/python_guide/index.md
@@ -25,6 +25,18 @@ To install `pyenv` on macOS, you can use [Homebrew](https://brew.sh/) with:
brew install pyenv
```
+### Windows
+
+`pyenv` does not officially support Windows and does not work in Windows outside the Windows Subsystem for Linux. If you are a Windows user, you can use `pyenv-win`.
+
+To install `pyenv-win` on Windows, run the following PowerShell command:
+
+```shell
+Invoke-WebRequest -UseBasicParsing -Uri "https://raw.githubusercontent.com/pyenv-win/pyenv-win/master/pyenv-win/install-pyenv-win.ps1" -OutFile "./install-pyenv-win.ps1"; &"./install-pyenv-win.ps1"
+```
+
+[Learn more about `pyenv-win`](https://github.com/pyenv-win/pyenv-win).
+
### Linux
To install `pyenv` on Linux, you can run the command below:
diff --git a/doc/development/rails_update.md b/doc/development/rails_update.md
index 1a30e606c17..8999ac90f4c 100644
--- a/doc/development/rails_update.md
+++ b/doc/development/rails_update.md
@@ -88,7 +88,7 @@ To efficiently and quickly find which Rails change caused the spec failure you c
For example, `git bisect start v6.1.4.1 v6.1.3.2` if we're upgrading from version 6.1.3.2 to 6.1.4.1.
Replace `<NEW_VERSION_TAG>` with the tag where the spec is red and `<OLD_VERSION_TAG>` with the one with the green spec. For example, `git bisect start v6.1.4.1 v6.1.3.2` if we're upgrading from version 6.1.3.2 to 6.1.4.1.
In the output, you can see how many steps approximately it takes to find the commit.
-1. Start the `git bisect` process and pass spec's file name(s) to `scripts/rails-update-bisect` as an argument or arguments. It can be faster to pick only one example instead of an entire spec file.
+1. Start the `git bisect` process and pass spec's filenames to `scripts/rails-update-bisect` as arguments. It can be faster to pick only one example instead of an entire spec file.
```shell
git bisect run <GDK_FOLDER>/gitlab/scripts/rails-update-bisect spec/models/ability_spec.rb
diff --git a/doc/development/testing_guide/end_to_end/beginners_guide.md b/doc/development/testing_guide/end_to_end/beginners_guide.md
index 27a87d25170..39a3e3445ea 100644
--- a/doc/development/testing_guide/end_to_end/beginners_guide.md
+++ b/doc/development/testing_guide/end_to_end/beginners_guide.md
@@ -49,7 +49,7 @@ For information about the distribution of tests per level in GitLab, see
- Review how often the feature changes. Stable features that don't change very often
might not be worth covering with end-to-end tests if they are already covered
in lower level tests.
-- Finally, discuss the proposed test with the developer(s) involved in implementing
+- Finally, discuss the proposed test with the developers involved in implementing
the feature and the lower-level tests.
WARNING:
diff --git a/doc/development/testing_guide/end_to_end/index.md b/doc/development/testing_guide/end_to_end/index.md
index 1e7cba9d247..9730115fd9f 100644
--- a/doc/development/testing_guide/end_to_end/index.md
+++ b/doc/development/testing_guide/end_to_end/index.md
@@ -147,11 +147,11 @@ as well as these:
| Variable | Description |
|-|-|
| `QA_SCENARIO` | The scenario to run (default `Test::Instance::Image`) |
-| `QA_TESTS` | The test(s) to run (no default, which means run all the tests in the scenario). Use file paths as you would when running tests via RSpec, for example, `qa/specs/features/ee/browser_ui` would include all the `EE` UI tests. |
+| `QA_TESTS` | The tests to run (no default, which means run all the tests in the scenario). Use file paths as you would when running tests via RSpec, for example, `qa/specs/features/ee/browser_ui` would include all the `EE` UI tests. |
| `QA_RSPEC_TAGS` | The RSpec tags to add (no default) |
-For now [manual jobs with custom variables don't use the same variable
-when retried](https://gitlab.com/gitlab-org/gitlab/-/issues/31367), so if you want to run the same test(s) multiple times,
+For now, [manual jobs with custom variables don't use the same variable
+when retried](https://gitlab.com/gitlab-org/gitlab/-/issues/31367), so if you want to run the same tests multiple times,
specify the same variables in each `custom-parallel` job (up to as
many of the 10 available jobs that you want to run).
diff --git a/doc/integration/elasticsearch.md b/doc/integration/elasticsearch.md
index 9ad709bea27..214bd845944 100644
--- a/doc/integration/elasticsearch.md
+++ b/doc/integration/elasticsearch.md
@@ -1083,7 +1083,7 @@ If `ElasticCommitIndexerWorker` Sidekiq workers are failing with this error duri
### Indexing is very slow or fails with `rejected execution of coordinating operation` messages
-Bulk requests are getting rejected by the Elasticsearch node(s) likely due to load and lack of available memory.
+Bulk requests getting rejected by the Elasticsearch nodes are likely due to load and lack of available memory.
Ensure that your Elasticsearch cluster meets the [system requirements](#system-requirements) and has enough resources
to perform bulk operations. See also the error ["429 (Too Many Requests)"](#indexing-fails-with-error-elastic-error-429-too-many-requests).
diff --git a/doc/integration/saml.md b/doc/integration/saml.md
index 5884429c8ca..ee4c34bb924 100644
--- a/doc/integration/saml.md
+++ b/doc/integration/saml.md
@@ -391,7 +391,7 @@ The requirements are the same as the previous settings:
- The IdP must pass Group information to GitLab.
- GitLab should know where to look for the groups in the SAML response, as well as which
- group(s) entail that a given user is an [auditor user](../user/permissions.md#auditor-users).
+ groups include users with the [Auditor role](../user/permissions.md#auditor-users).
```yaml
{ name: 'saml',
diff --git a/doc/operations/incident_management/alerts.md b/doc/operations/incident_management/alerts.md
index 5eb0624be31..008e41f5d64 100644
--- a/doc/operations/incident_management/alerts.md
+++ b/doc/operations/incident_management/alerts.md
@@ -202,7 +202,7 @@ To assign an alert:
1. Select your desired alert to display its details.
- ![Alert Details View Assignee(s)](img/alert_details_assignees_v13_1.png)
+ ![Alert Details View Assignees](img/alert_details_assignees_v13_1.png)
1. If the right sidebar is not expanded, select
**Expand sidebar** (**{angle-double-right}**) to expand it.
diff --git a/doc/operations/incident_management/paging.md b/doc/operations/incident_management/paging.md
index d0c14ab6e59..420454d8d8a 100644
--- a/doc/operations/incident_management/paging.md
+++ b/doc/operations/incident_management/paging.md
@@ -38,7 +38,7 @@ a single email notification for new alerts.
## Paging **(PREMIUM)**
-In projects that have an [escalation policy](escalation_policies.md) configured, on-call responder(s)
+In projects that have an [escalation policy](escalation_policies.md) configured, on-call responders
can be automatically paged about critical problems through email.
### Escalating an alert
diff --git a/doc/security/asset_proxy.md b/doc/security/asset_proxy.md
index e4849b1b658..1ccc9bfd9be 100644
--- a/doc/security/asset_proxy.md
+++ b/doc/security/asset_proxy.md
@@ -48,11 +48,11 @@ To install a Camo server as an asset proxy:
| Attribute | Description |
|:-------------------------|:-------------------------------------------------------------------------------------------------------------------------------------|
- | `asset_proxy_enabled` | Enable proxying of assets. If enabled, requires: `asset_proxy_url`). |
+ | `asset_proxy_enabled` | Enable proxying of assets. If enabled, requires: `asset_proxy_url`. |
| `asset_proxy_secret_key` | Shared secret with the asset proxy server. |
| `asset_proxy_url` | URL of the asset proxy server. |
- | `asset_proxy_whitelist` | (Deprecated: Use `asset_proxy_allowlist` instead) Assets that match these domain(s) are NOT proxied. Wildcards allowed. Your GitLab installation URL is automatically allowed. |
- | `asset_proxy_allowlist` | Assets that match these domain(s) are NOT proxied. Wildcards allowed. Your GitLab installation URL is automatically allowed. |
+ | `asset_proxy_whitelist` | (Deprecated: Use `asset_proxy_allowlist` instead) Assets that match these domains are NOT proxied. Wildcards allowed. Your GitLab installation URL is automatically allowed. |
+ | `asset_proxy_allowlist` | Assets that match these domains are NOT proxied. Wildcards allowed. Your GitLab installation URL is automatically allowed. |
1. Restart the server for the changes to take effect. Each time you change any values for the asset
proxy, you need to restart the server.
diff --git a/doc/topics/autodevops/prepare_deployment.md b/doc/topics/autodevops/prepare_deployment.md
index c23774b1ffd..7c9bf5a770e 100644
--- a/doc/topics/autodevops/prepare_deployment.md
+++ b/doc/topics/autodevops/prepare_deployment.md
@@ -51,7 +51,7 @@ as other environment [variables](../../ci/variables/index.md#cicd-variable-prece
If you don't specify the base domain in your projects and groups, Auto DevOps uses the instance-wide **Auto DevOps domain**.
-Auto DevOps requires a wildcard DNS A record matching the base domain(s). For
+Auto DevOps requires a wildcard DNS A record matching the base domains. For
a base domain of `example.com`, you'd need a DNS entry like:
```plaintext
diff --git a/doc/topics/autodevops/requirements.md b/doc/topics/autodevops/requirements.md
index 816cbbece4f..820db481433 100644
--- a/doc/topics/autodevops/requirements.md
+++ b/doc/topics/autodevops/requirements.md
@@ -69,7 +69,7 @@ as other environment [variables](../../ci/variables/index.md#cicd-variable-prece
If you don't specify the base domain in your projects and groups, Auto DevOps uses the instance-wide **Auto DevOps domain**.
-Auto DevOps requires a wildcard DNS A record matching the base domain(s). For
+Auto DevOps requires a wildcard DNS record that matches the base domains. For
a base domain of `example.com`, you'd need a DNS entry like:
```plaintext
diff --git a/doc/user/admin_area/settings/account_and_limit_settings.md b/doc/user/admin_area/settings/account_and_limit_settings.md
index fe713baeb39..4dfb9ef90dc 100644
--- a/doc/user/admin_area/settings/account_and_limit_settings.md
+++ b/doc/user/admin_area/settings/account_and_limit_settings.md
@@ -78,7 +78,7 @@ To modify the maximum file size for exports in GitLab:
## Max import size
-> [Modified](https://gitlab.com/gitlab-org/gitlab/-/issues/251106) from 50 MB to unlimited in GitLab 13.8.
+> [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/251106) from 50 MB to unlimited in GitLab 13.8.
To modify the maximum file size for imports in GitLab:
diff --git a/doc/user/application_security/api_fuzzing/index.md b/doc/user/application_security/api_fuzzing/index.md
index 22881e216f7..f97e09f33bb 100644
--- a/doc/user/application_security/api_fuzzing/index.md
+++ b/doc/user/application_security/api_fuzzing/index.md
@@ -1467,7 +1467,7 @@ reported.
Faults detected by API Fuzzing occur in the live web application, and require manual investigation
to determine if they are vulnerabilities. Fuzzing faults are included as vulnerabilities with a
severity of Unknown. To facilitate investigation of the fuzzing faults, detailed information is
-provided about the HTTP messages sent and received along with a description of the modification(s)
+provided about the HTTP messages sent and received along with a description of the modifications
made.
Follow these steps to view details of a fuzzing fault:
diff --git a/doc/user/application_security/dast/checks/16.5.md b/doc/user/application_security/dast/checks/16.5.md
index 28bb9f7ee4b..e03da3043ef 100644
--- a/doc/user/application_security/dast/checks/16.5.md
+++ b/doc/user/application_security/dast/checks/16.5.md
@@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
## Description
-The target website returns AspNet header(s) and version information of this website. By
+The target website returns AspNet headers and version information of this website. By
exposing these values attackers may attempt to identify if the target software is vulnerable to known
vulnerabilities, or catalog known sites running particular versions to exploit in the future when a
vulnerability is identified in the particular version.
diff --git a/doc/user/search/img/issue_search_by_id_v15_0.png b/doc/user/search/img/issue_search_by_id_v15_0.png
index f2a47984ac9..411cebc0ccb 100644
--- a/doc/user/search/img/issue_search_by_id_v15_0.png
+++ b/doc/user/search/img/issue_search_by_id_v15_0.png
Binary files differ
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index f3d7650693d..a079c591519 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -394,7 +394,14 @@ module API
end
def order_options_with_tie_breaker
- order_options = { params[:order_by] => params[:sort] }
+ order_by = if Feature.enabled?(:replace_order_by_created_at_with_id) &&
+ params[:order_by] == 'created_at'
+ 'id'
+ else
+ params[:order_by]
+ end
+
+ order_options = { order_by => params[:sort] }
order_options['id'] ||= params[:sort] || 'asc'
order_options
end
diff --git a/lib/container_registry/migration.rb b/lib/container_registry/migration.rb
index c1628e99768..8377190c83c 100644
--- a/lib/container_registry/migration.rb
+++ b/lib/container_registry/migration.rb
@@ -74,5 +74,9 @@ module ContainerRegistry
def self.enqueue_twice?
Feature.enabled?(:container_registry_migration_phase2_enqueue_twice)
end
+
+ def self.enqueuer_loop?
+ Feature.enabled?(:container_registry_migration_phase2_enqueuer_loop)
+ end
end
end
diff --git a/lib/gitlab/ci/templates/Jobs/Dependency-Scanning.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Dependency-Scanning.gitlab-ci.yml
index 7c6122aa419..f2b9cb82e22 100644
--- a/lib/gitlab/ci/templates/Jobs/Dependency-Scanning.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Dependency-Scanning.gitlab-ci.yml
@@ -152,3 +152,21 @@ gemnasium-python-dependency_scanning:
- if: $CI_COMMIT_BRANCH &&
$GITLAB_FEATURES =~ /\bdependency_scanning\b/ &&
$PIP_REQUIREMENTS_FILE
+
+bundler-audit-dependency_scanning:
+ allow_failure: true
+ script:
+ - echo "This job was deprecated in GitLab 14.8 and removed in GitLab 15.0"
+ - echo "For more information see https://gitlab.com/gitlab-org/gitlab/-/issues/347491"
+ - exit 1
+ rules:
+ - when: never
+
+retire-js-dependency_scanning:
+ allow_failure: true
+ script:
+ - echo "This job was deprecated in GitLab 14.8 and removed in GitLab 15.0"
+ - echo "For more information see https://gitlab.com/gitlab-org/gitlab/-/issues/289830"
+ - exit 1
+ rules:
+ - when: never
diff --git a/lib/gitlab/ci/templates/Ruby.gitlab-ci.yml b/lib/gitlab/ci/templates/Ruby.gitlab-ci.yml
index 33c0928db6f..44f959468a8 100644
--- a/lib/gitlab/ci/templates/Ruby.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Ruby.gitlab-ci.yml
@@ -29,7 +29,7 @@ before_script:
- ruby -v # Print out ruby version for debugging
# Uncomment next line if your rails app needs a JS runtime:
# - apt-get update -q && apt-get install nodejs -yqq
- - bundle config set path 'vendor' # Install dependencies into ./vendor/ruby
+ - bundle config set --local deployment true # Install dependencies into ./vendor/ruby
- bundle install -j $(nproc)
# Optional - Delete if not using `rubocop`
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index d275513fdfc..e989cd59861 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -17039,6 +17039,9 @@ msgstr ""
msgid "GitLab"
msgstr ""
+msgid "GitLab (self-managed)"
+msgstr ""
+
msgid "GitLab / Unsubscribe"
msgstr ""
@@ -17153,6 +17156,9 @@ msgstr ""
msgid "GitLab.com"
msgstr ""
+msgid "GitLab.com (SaaS)"
+msgstr ""
+
msgid "GitLab.com import"
msgstr ""
@@ -21600,6 +21606,9 @@ msgstr ""
msgid "JiraService|Base URL of the Jira instance."
msgstr ""
+msgid "JiraService|Change GitLab version"
+msgstr ""
+
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -21633,9 +21642,15 @@ msgstr ""
msgid "JiraService|For example, AB"
msgstr ""
+msgid "JiraService|For example: https://gitlab.example.com"
+msgstr ""
+
msgid "JiraService|GitLab for Jira Configuration"
msgstr ""
+msgid "JiraService|GitLab instance URL"
+msgstr ""
+
msgid "JiraService|IDs must be a list of numbers that can be split with , or ;"
msgstr ""
@@ -21684,6 +21699,9 @@ msgstr ""
msgid "JiraService|Set a custom final state by using transition IDs. %{linkStart}Learn about transition IDs%{linkEnd}"
msgstr ""
+msgid "JiraService|Sign in to GitLab to link namespaces."
+msgstr ""
+
msgid "JiraService|Sign in to GitLab.com to get started."
msgstr ""
@@ -21726,6 +21744,12 @@ msgstr ""
msgid "JiraService|Web URL"
msgstr ""
+msgid "JiraService|Welcome to GitLab for Jira"
+msgstr ""
+
+msgid "JiraService|What version of GitLab are you using?"
+msgstr ""
+
msgid "JiraService|When a Jira issue is mentioned in a commit or merge request, a remote link and comment (if enabled) will be created."
msgstr ""
@@ -24775,6 +24799,9 @@ msgstr ""
msgid "More topics"
msgstr ""
+msgid "Most common"
+msgstr ""
+
msgid "Most relevant"
msgstr ""
diff --git a/package.json b/package.json
index eed49746743..f6a716b7312 100644
--- a/package.json
+++ b/package.json
@@ -120,7 +120,7 @@
"dateformat": "^5.0.1",
"deckar01-task_list": "^2.3.1",
"diff": "^3.4.0",
- "dompurify": "^2.3.7",
+ "dompurify": "^2.3.8",
"dropzone": "^4.2.0",
"editorconfig": "^0.15.3",
"emoji-regex": "^10.0.0",
@@ -145,7 +145,7 @@
"lowlight": "^2.5.0",
"marked": "^0.3.12",
"mathjax": "3",
- "mermaid": "^9.0.1",
+ "mermaid": "^9.1.1",
"minimatch": "^3.0.4",
"monaco-editor": "^0.25.2",
"monaco-editor-webpack-plugin": "^4.0.0",
diff --git a/spec/frontend/fixtures/api_merge_requests.rb b/spec/frontend/fixtures/api_merge_requests.rb
index 47321fbbeaa..75bc8c8df25 100644
--- a/spec/frontend/fixtures/api_merge_requests.rb
+++ b/spec/frontend/fixtures/api_merge_requests.rb
@@ -9,11 +9,13 @@ RSpec.describe API::MergeRequests, '(JavaScript fixtures)', type: :request do
let_it_be(:admin) { create(:admin, name: 'root') }
let_it_be(:namespace) { create(:namespace, name: 'gitlab-test' )}
let_it_be(:project) { create(:project, :repository, namespace: namespace, path: 'lorem-ipsum') }
+ let_it_be(:early_mrs) do
+ 4.times { |i| create(:merge_request, source_project: project, source_branch: "branch-#{i}") }
+ end
+
let_it_be(:mr) { create(:merge_request, source_project: project) }
it 'api/merge_requests/get.json' do
- 4.times { |i| create(:merge_request, source_project: project, source_branch: "branch-#{i}") }
-
get api("/projects/#{project.id}/merge_requests", admin)
expect(response).to be_successful
diff --git a/spec/frontend/issues/list/mock_data.js b/spec/frontend/issues/list/mock_data.js
index 46f342cc673..42f2d08082e 100644
--- a/spec/frontend/issues/list/mock_data.js
+++ b/spec/frontend/issues/list/mock_data.js
@@ -117,6 +117,7 @@ export const locationSearch = [
'not[author_username]=marge',
'assignee_username[]=bart',
'assignee_username[]=lisa',
+ 'assignee_username[]=5',
'not[assignee_username][]=patty',
'not[assignee_username][]=selma',
'milestone_title=season+3',
@@ -167,6 +168,7 @@ export const filteredTokens = [
{ type: 'author_username', value: { data: 'marge', operator: OPERATOR_IS_NOT } },
{ type: 'assignee_username', value: { data: 'bart', operator: OPERATOR_IS } },
{ type: 'assignee_username', value: { data: 'lisa', operator: OPERATOR_IS } },
+ { type: 'assignee_username', value: { data: '5', operator: OPERATOR_IS } },
{ type: 'assignee_username', value: { data: 'patty', operator: OPERATOR_IS_NOT } },
{ type: 'assignee_username', value: { data: 'selma', operator: OPERATOR_IS_NOT } },
{ type: 'milestone', value: { data: 'season 3', operator: OPERATOR_IS } },
@@ -216,7 +218,7 @@ export const filteredTokensWithSpecialValues = [
export const apiParams = {
authorUsername: 'homer',
- assigneeUsernames: ['bart', 'lisa'],
+ assigneeUsernames: ['bart', 'lisa', '5'],
milestoneTitle: ['season 3', 'season 4'],
labelName: ['cartoon', 'tv'],
releaseTag: ['v3', 'v4'],
@@ -257,7 +259,7 @@ export const apiParamsWithSpecialValues = {
export const urlParams = {
author_username: 'homer',
'not[author_username]': 'marge',
- 'assignee_username[]': ['bart', 'lisa'],
+ 'assignee_username[]': ['bart', 'lisa', '5'],
'not[assignee_username][]': ['patty', 'selma'],
milestone_title: ['season 3', 'season 4'],
'not[milestone_title]': ['season 20', 'season 30'],
diff --git a/spec/frontend/issues/list/utils_spec.js b/spec/frontend/issues/list/utils_spec.js
index c0bec105c40..ce0477883d7 100644
--- a/spec/frontend/issues/list/utils_spec.js
+++ b/spec/frontend/issues/list/utils_spec.js
@@ -1,3 +1,5 @@
+import setWindowLocation from 'helpers/set_window_location_helper';
+import { TEST_HOST } from 'helpers/test_constants';
import {
apiParams,
apiParamsWithSpecialValues,
@@ -142,21 +144,33 @@ describe('getFilterTokens', () => {
});
describe('convertToApiParams', () => {
+ beforeEach(() => {
+ setWindowLocation(TEST_HOST);
+ });
+
it('returns api params given filtered tokens', () => {
expect(convertToApiParams(filteredTokens)).toEqual(apiParams);
});
it('returns api params given filtered tokens with special values', () => {
+ setWindowLocation('?assignee_id=123');
+
expect(convertToApiParams(filteredTokensWithSpecialValues)).toEqual(apiParamsWithSpecialValues);
});
});
describe('convertToUrlParams', () => {
+ beforeEach(() => {
+ setWindowLocation(TEST_HOST);
+ });
+
it('returns url params given filtered tokens', () => {
expect(convertToUrlParams(filteredTokens)).toEqual(urlParams);
});
it('returns url params given filtered tokens with special values', () => {
+ setWindowLocation('?assignee_id=123');
+
expect(convertToUrlParams(filteredTokensWithSpecialValues)).toEqual(urlParamsWithSpecialValues);
});
});
diff --git a/spec/frontend/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_multiversion/index_spec.js b/spec/frontend/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_multiversion/index_spec.js
new file mode 100644
index 00000000000..f4be8bf121d
--- /dev/null
+++ b/spec/frontend/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_multiversion/index_spec.js
@@ -0,0 +1,83 @@
+import { nextTick } from 'vue';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+
+import SignInGitlabMultiversion from '~/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_multiversion/index.vue';
+import VersionSelectForm from '~/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_multiversion/version_select_form.vue';
+import SignInOauthButton from '~/jira_connect/subscriptions/components/sign_in_oauth_button.vue';
+
+describe('SignInGitlabMultiversion', () => {
+ let wrapper;
+
+ const findVersionSelectForm = () => wrapper.findComponent(VersionSelectForm);
+ const findSignInOauthButton = () => wrapper.findComponent(SignInOauthButton);
+ const findSubtitle = () => wrapper.findByTestId('subtitle');
+
+ const createComponent = () => {
+ wrapper = shallowMountExtended(SignInGitlabMultiversion);
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('when version is not selected', () => {
+ describe('VersionSelectForm', () => {
+ it('renders version select form', () => {
+ createComponent();
+
+ expect(findVersionSelectForm().exists()).toBe(true);
+ });
+
+ describe('when form emits "submit" event', () => {
+ it('hides the version select form and shows the sign in button', async () => {
+ createComponent();
+
+ findVersionSelectForm().vm.$emit('submit', 'gitlab.mycompany.com');
+ await nextTick();
+
+ expect(findVersionSelectForm().exists()).toBe(false);
+ expect(findSignInOauthButton().exists()).toBe(true);
+ });
+ });
+ });
+ });
+
+ describe('when version is selected', () => {
+ beforeEach(async () => {
+ createComponent();
+
+ findVersionSelectForm().vm.$emit('submit', 'gitlab.mycompany.com');
+ await nextTick();
+ });
+
+ describe('sign in button', () => {
+ it('renders sign in button', () => {
+ expect(findSignInOauthButton().exists()).toBe(true);
+ });
+
+ describe('when button emits `sign-in` event', () => {
+ it('emits `sign-in-oauth` event', () => {
+ const button = findSignInOauthButton();
+
+ const mockUser = { name: 'test' };
+ button.vm.$emit('sign-in', mockUser);
+
+ expect(wrapper.emitted('sign-in-oauth')[0]).toEqual([mockUser]);
+ });
+ });
+
+ describe('when button emits `error` event', () => {
+ it('emits `error` event', () => {
+ const button = findSignInOauthButton();
+ button.vm.$emit('error');
+
+ expect(wrapper.emitted('error')).toBeTruthy();
+ });
+ });
+ });
+
+ it('renders correct subtitle', () => {
+ expect(findSubtitle().text()).toBe(SignInGitlabMultiversion.i18n.signInSubtitle);
+ });
+ });
+});
diff --git a/spec/frontend/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_multiversion/version_select_form_spec.js b/spec/frontend/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_multiversion/version_select_form_spec.js
new file mode 100644
index 00000000000..29e7fe7a5b2
--- /dev/null
+++ b/spec/frontend/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_multiversion/version_select_form_spec.js
@@ -0,0 +1,69 @@
+import { GlFormInput, GlFormRadioGroup, GlForm } from '@gitlab/ui';
+import { nextTick } from 'vue';
+
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import VersionSelectForm from '~/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_multiversion/version_select_form.vue';
+
+describe('VersionSelectForm', () => {
+ let wrapper;
+
+ const findFormRadioGroup = () => wrapper.findComponent(GlFormRadioGroup);
+ const findForm = () => wrapper.findComponent(GlForm);
+ const findInput = () => wrapper.findComponent(GlFormInput);
+
+ const submitForm = () => findForm().vm.$emit('submit', new Event('submit'));
+
+ const createComponent = () => {
+ wrapper = shallowMountExtended(VersionSelectForm);
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('default state', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('selects saas radio option by default', () => {
+ expect(findFormRadioGroup().vm.$attrs.checked).toBe(VersionSelectForm.radioOptions.saas);
+ });
+
+ it('does not render instance input', () => {
+ expect(findInput().exists()).toBe(false);
+ });
+
+ describe('when form is submitted', () => {
+ it('emits "submit" event with gitlab.com as the payload', () => {
+ submitForm();
+
+ expect(wrapper.emitted('submit')[0][0]).toBe('https://gitlab.com');
+ });
+ });
+ });
+
+ describe('when "self-managed" radio option is selected', () => {
+ beforeEach(async () => {
+ createComponent();
+
+ findFormRadioGroup().vm.$emit('input', VersionSelectForm.radioOptions.selfManaged);
+ await nextTick();
+ });
+
+ it('reveals the self-managed input field', () => {
+ expect(findInput().exists()).toBe(true);
+ });
+
+ describe('when form is submitted', () => {
+ it('emits "submit" event with the input field value as the payload', () => {
+ const mockInstanceUrl = 'https://gitlab.example.com';
+
+ findInput().vm.$emit('input', mockInstanceUrl);
+ submitForm();
+
+ expect(wrapper.emitted('submit')[0][0]).toBe(mockInstanceUrl);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/jira_connect/subscriptions/pages/sign_in/sign_in_page_spec.js b/spec/frontend/jira_connect/subscriptions/pages/sign_in/sign_in_page_spec.js
index 94e41257784..24aa6e2beaa 100644
--- a/spec/frontend/jira_connect/subscriptions/pages/sign_in/sign_in_page_spec.js
+++ b/spec/frontend/jira_connect/subscriptions/pages/sign_in/sign_in_page_spec.js
@@ -2,7 +2,7 @@ import { shallowMount } from '@vue/test-utils';
import SignInPage from '~/jira_connect/subscriptions/pages/sign_in/sign_in_page.vue';
import SignInGitlabCom from '~/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_com.vue';
-import SignInGitlabMultiversion from '~/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_multiversion.vue';
+import SignInGitlabMultiversion from '~/jira_connect/subscriptions/pages/sign_in/sign_in_gitlab_multiversion/index.vue';
import createStore from '~/jira_connect/subscriptions/store';
describe('SignInPage', () => {
diff --git a/spec/frontend/lib/utils/datetime_utility_spec.js b/spec/frontend/lib/utils/datetime_utility_spec.js
index 9459878ded0..8d989350173 100644
--- a/spec/frontend/lib/utils/datetime_utility_spec.js
+++ b/spec/frontend/lib/utils/datetime_utility_spec.js
@@ -309,7 +309,7 @@ describe('datefix', () => {
describe('parsePikadayDate', () => {
it('should return a UTC date', () => {
- expect(datetimeUtility.parsePikadayDate('2020-01-29')).toEqual(new Date('2020-01-29'));
+ expect(datetimeUtility.parsePikadayDate('2020-01-29')).toEqual(new Date(2020, 0, 29));
});
});
diff --git a/spec/lib/api/helpers_spec.rb b/spec/lib/api/helpers_spec.rb
index e8cc289174c..78ce9642392 100644
--- a/spec/lib/api/helpers_spec.rb
+++ b/spec/lib/api/helpers_spec.rb
@@ -588,7 +588,7 @@ RSpec.describe API::Helpers do
end
end
- describe '#order_options_with_tie_breaker' do
+ shared_examples '#order_options_with_tie_breaker' do
subject { Class.new.include(described_class).new.order_options_with_tie_breaker }
before do
@@ -630,6 +630,30 @@ RSpec.describe API::Helpers do
end
end
+ describe '#order_options_with_tie_breaker' do
+ include_examples '#order_options_with_tie_breaker'
+
+ context 'with created_at order given' do
+ let(:params) { { order_by: 'created_at', sort: 'asc' } }
+
+ it 'converts to id' do
+ is_expected.to eq({ 'id' => 'asc' })
+ end
+
+ context 'when replace_order_by_created_at_with_id feature flag is disabled' do
+ before do
+ stub_feature_flags(replace_order_by_created_at_with_id: false)
+ end
+
+ include_examples '#order_options_with_tie_breaker'
+
+ it 'maintains created_at order' do
+ is_expected.to eq({ 'created_at' => 'asc', 'id' => 'asc' })
+ end
+ end
+ end
+ end
+
describe "#destroy_conditionally!" do
let!(:project) { create(:project) }
diff --git a/spec/lib/container_registry/migration_spec.rb b/spec/lib/container_registry/migration_spec.rb
index 7e8fcd65930..81dac354b8b 100644
--- a/spec/lib/container_registry/migration_spec.rb
+++ b/spec/lib/container_registry/migration_spec.rb
@@ -227,4 +227,18 @@ RSpec.describe ContainerRegistry::Migration do
it { is_expected.to eq(false) }
end
end
+
+ describe '.enqueue_loop?' do
+ subject { described_class.enqueuer_loop? }
+
+ it { is_expected.to eq(true) }
+
+ context 'feature flag disabled' do
+ before do
+ stub_feature_flags(container_registry_migration_phase2_enqueuer_loop: false)
+ end
+
+ it { is_expected.to eq(false) }
+ end
+ end
end
diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb
index b1183bb10fa..a7ede7f4150 100644
--- a/spec/requests/api/merge_requests_spec.rb
+++ b/spec/requests/api/merge_requests_spec.rb
@@ -27,10 +27,10 @@ RSpec.describe API::MergeRequests do
shared_context 'with merge requests' do
let_it_be(:milestone1) { create(:milestone, title: '0.9', project: project) }
- let_it_be(:merge_request) { create(:merge_request, :simple, milestone: milestone1, author: user, assignees: [user], source_project: project, target_project: project, source_branch: 'markdown', title: "Test", created_at: base_time) }
- let_it_be(:merge_request_closed) { create(:merge_request, state: "closed", milestone: milestone1, author: user, assignees: [user], source_project: project, target_project: project, title: "Closed test", created_at: base_time + 1.second) }
- let_it_be(:merge_request_merged) { create(:merge_request, state: "merged", author: user, assignees: [user], source_project: project, target_project: project, title: "Merged test", created_at: base_time + 2.seconds, merge_commit_sha: '9999999999999999999999999999999999999999') }
- let_it_be(:merge_request_locked) { create(:merge_request, state: "locked", milestone: milestone1, author: user, assignees: [user], source_project: project, target_project: project, title: "Locked test", created_at: base_time + 1.second) }
+ let_it_be(:merge_request) { create(:merge_request, :simple, milestone: milestone1, author: user, assignees: [user], source_project: project, target_project: project, source_branch: 'markdown', title: "Test", created_at: base_time, updated_at: base_time + 3.hours) }
+ let_it_be(:merge_request_closed) { create(:merge_request, state: "closed", milestone: milestone1, author: user, assignees: [user], source_project: project, target_project: project, title: "Closed test", created_at: base_time + 1.second, updated_at: base_time) }
+ let_it_be(:merge_request_locked) { create(:merge_request, state: "locked", milestone: milestone1, author: user, assignees: [user], source_project: project, target_project: project, title: "Locked test", created_at: base_time + 1.second, updated_at: base_time + 2.hours) }
+ let_it_be(:merge_request_merged) { create(:merge_request, state: "merged", author: user, assignees: [user], source_project: project, target_project: project, title: "Merged test", created_at: base_time + 2.seconds, updated_at: base_time + 1.hour, merge_commit_sha: '9999999999999999999999999999999999999999') }
let_it_be(:note) { create(:note_on_merge_request, author: user, project: project, noteable: merge_request, note: "a comment on a MR") }
let_it_be(:note2) { create(:note_on_merge_request, author: user, project: project, noteable: merge_request, note: "another comment on a MR") }
end
@@ -348,19 +348,14 @@ RSpec.describe API::MergeRequests do
end
context 'with ordering' do
- before do
- @mr_later = mr_with_later_created_and_updated_at_time
- @mr_earlier = mr_with_earlier_created_and_updated_at_time
- end
-
it 'returns an array of merge_requests in ascending order' do
path = endpoint_path + '?sort=asc'
get api(path, user)
expect_paginated_array_response([
- merge_request_closed.id, merge_request_locked.id,
- merge_request_merged.id, merge_request.id
+ merge_request.id, merge_request_closed.id,
+ merge_request_locked.id, merge_request_merged.id
])
response_dates = json_response.map { |merge_request| merge_request['created_at'] }
expect(response_dates).to eq(response_dates.sort)
@@ -372,42 +367,28 @@ RSpec.describe API::MergeRequests do
get api(path, user)
expect_paginated_array_response([
- merge_request.id, merge_request_merged.id,
- merge_request_locked.id, merge_request_closed.id
+ merge_request_merged.id, merge_request_locked.id,
+ merge_request_closed.id, merge_request.id
])
response_dates = json_response.map { |merge_request| merge_request['created_at'] }
expect(response_dates).to eq(response_dates.sort.reverse)
end
context '2 merge requests with equal created_at' do
- let!(:closed_mr2) do
- create :merge_request,
- state: 'closed',
- milestone: milestone1,
- author: user,
- assignees: [user],
- source_project: project,
- target_project: project,
- title: "Test",
- created_at: @mr_earlier.created_at
- end
-
it 'page breaks first page correctly' do
- get api("#{endpoint_path}?sort=desc&per_page=4", user)
+ get api("#{endpoint_path}?sort=desc&per_page=2", user)
response_ids = json_response.map { |merge_request| merge_request['id'] }
- expect(response_ids).to include(closed_mr2.id)
- expect(response_ids).not_to include(@mr_earlier.id)
+ expect(response_ids).to contain_exactly(merge_request_merged.id, merge_request_locked.id)
end
it 'page breaks second page correctly' do
- get api("#{endpoint_path}?sort=desc&per_page=4&page=2", user)
+ get api("#{endpoint_path}?sort=desc&per_page=2&page=2", user)
response_ids = json_response.map { |merge_request| merge_request['id'] }
- expect(response_ids).not_to include(closed_mr2.id)
- expect(response_ids).to include(@mr_earlier.id)
+ expect(response_ids).to contain_exactly(merge_request_closed.id, merge_request.id)
end
end
@@ -430,8 +411,8 @@ RSpec.describe API::MergeRequests do
get api(path, user)
expect_paginated_array_response([
- merge_request_closed.id, merge_request_locked.id,
- merge_request_merged.id, merge_request.id
+ merge_request.id, merge_request_closed.id,
+ merge_request_locked.id, merge_request_merged.id
])
response_dates = json_response.map { |merge_request| merge_request['created_at'] }
expect(response_dates).to eq(response_dates.sort)
@@ -3379,20 +3360,4 @@ RSpec.describe API::MergeRequests do
include_examples 'time tracking endpoints', 'merge_request'
end
-
- def mr_with_later_created_and_updated_at_time
- merge_request
- merge_request.created_at += 1.hour
- merge_request.updated_at += 30.minutes
- merge_request.save!
- merge_request
- end
-
- def mr_with_earlier_created_and_updated_at_time
- merge_request_closed
- merge_request_closed.created_at -= 1.hour
- merge_request_closed.updated_at -= 30.minutes
- merge_request_closed.save!
- merge_request_closed
- end
end
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index 20d371bdd4b..11ac10e9d6d 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -739,6 +739,32 @@ RSpec.describe API::Projects do
end
end
+ context 'with default created_at desc order' do
+ let_it_be(:group_with_projects) { create(:group) }
+ let_it_be(:project_1) { create(:project, name: 'Project 1', created_at: 3.days.ago, path: 'project1', group: group_with_projects) }
+ let_it_be(:project_2) { create(:project, name: 'Project 2', created_at: 2.days.ago, path: 'project2', group: group_with_projects) }
+ let_it_be(:project_3) { create(:project, name: 'Project 3', created_at: 1.day.ago, path: 'project3', group: group_with_projects) }
+
+ let(:current_user) { user }
+ let(:params) { {} }
+
+ subject { get api('/projects', current_user), params: params }
+
+ before do
+ group_with_projects.add_owner(current_user) if current_user
+ end
+
+ it 'orders by id desc instead' do
+ projects_ordered_by_id_desc = /SELECT "projects".+ORDER BY "projects"."id" DESC/i
+ expect { subject }.to make_queries_matching projects_ordered_by_id_desc
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.first['id']).to eq(project_3.id)
+ end
+ end
+
context 'sorting' do
context 'by project statistics' do
%w(repository_size storage_size wiki_size packages_size).each do |order_by|
diff --git a/spec/support/helpers/namespaces_test_helper.rb b/spec/support/helpers/namespaces_test_helper.rb
new file mode 100644
index 00000000000..9762c38a9bb
--- /dev/null
+++ b/spec/support/helpers/namespaces_test_helper.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module NamespacesTestHelper
+ def get_buy_minutes_path(namespace)
+ buy_minutes_subscriptions_path(selected_group: namespace.id)
+ end
+
+ def get_buy_storage_path(namespace)
+ buy_storage_subscriptions_path(selected_group: namespace.id)
+ end
+end
+
+NamespacesTestHelper.prepend_mod
diff --git a/spec/workers/container_registry/migration/enqueuer_worker_spec.rb b/spec/workers/container_registry/migration/enqueuer_worker_spec.rb
index d21fa589f98..9977cc1a5f0 100644
--- a/spec/workers/container_registry/migration/enqueuer_worker_spec.rb
+++ b/spec/workers/container_registry/migration/enqueuer_worker_spec.rb
@@ -23,318 +23,669 @@ RSpec.describe ContainerRegistry::Migration::EnqueuerWorker, :aggregate_failures
shared_examples 'no action' do
it 'does not queue or change any repositories' do
+ expect(worker).not_to receive(:handle_next_migration)
+ expect(worker).not_to receive(:handle_aborted_migration)
+
subject
expect(container_repository.reload).to be_default
end
end
- shared_examples 're-enqueuing based on capacity' do |capacity_limit: 4|
- context 'below capacity' do
+ context 'with container_registry_migration_phase2_enqueuer_loop disabled' do
+ before do
+ stub_feature_flags(container_registry_migration_phase2_enqueuer_loop: false)
+ end
+
+ shared_examples 're-enqueuing based on capacity' do |capacity_limit: 4|
+ context 'below capacity' do
+ before do
+ allow(ContainerRegistry::Migration).to receive(:capacity).and_return(capacity_limit)
+ end
+
+ it 're-enqueues the worker' do
+ expect(described_class).to receive(:perform_async)
+ expect(described_class).to receive(:perform_in).with(7.seconds)
+
+ subject
+ end
+
+ context 'enqueue_twice feature flag disabled' do
+ before do
+ stub_feature_flags(container_registry_migration_phase2_enqueue_twice: false)
+ end
+
+ it 'only enqueues the worker once' do
+ expect(described_class).to receive(:perform_async)
+ expect(described_class).not_to receive(:perform_in)
+
+ subject
+ end
+ end
+ end
+
+ context 'above capacity' do
+ before do
+ allow(ContainerRegistry::Migration).to receive(:capacity).and_return(-1)
+ end
+
+ it 'does not re-enqueue the worker' do
+ expect(described_class).not_to receive(:perform_async)
+ expect(described_class).not_to receive(:perform_in).with(7.seconds)
+
+ subject
+ end
+ end
+ end
+
+ context 'with qualified repository' do
before do
- allow(ContainerRegistry::Migration).to receive(:capacity).and_return(capacity_limit)
+ allow_worker(on: :next_repository) do |repository|
+ allow(repository).to receive(:migration_pre_import).and_return(:ok)
+ end
end
- it 're-enqueues the worker' do
- expect(described_class).to receive(:perform_async)
- expect(described_class).to receive(:perform_in).with(7.seconds)
+ shared_examples 'starting the next import' do
+ it 'starts the pre-import for the next qualified repository' do
+ expect_log_extra_metadata(
+ import_type: 'next',
+ container_repository_id: container_repository.id,
+ container_repository_path: container_repository.path,
+ container_repository_migration_state: 'pre_importing'
+ )
- subject
+ subject
+
+ expect(container_repository.reload).to be_pre_importing
+ end
end
- context 'enqueue_twice feature flag disabled' do
+ it_behaves_like 'starting the next import'
+
+ context 'when the new pre-import maxes out the capacity' do
before do
- stub_feature_flags(container_registry_migration_phase2_enqueue_twice: false)
+ # set capacity to 10
+ stub_feature_flags(
+ container_registry_migration_phase2_capacity_25: false
+ )
+
+ # Plus 2 created above gives 9 importing repositories
+ create_list(:container_repository, 7, :importing)
end
- it 'only enqueues the worker once' do
- expect(described_class).to receive(:perform_async)
+ it 'does not re-enqueue the worker' do
+ expect(described_class).not_to receive(:perform_async)
expect(described_class).not_to receive(:perform_in)
subject
end
end
+
+ it_behaves_like 're-enqueuing based on capacity'
+
+ context 'max tag count is 0' do
+ before do
+ stub_application_setting(container_registry_import_max_tags_count: 0)
+ # Add 8 tags to the next repository
+ stub_container_registry_tags(
+ repository: container_repository.path, tags: %w(a b c d e f g h), with_manifest: true
+ )
+ end
+
+ it_behaves_like 'starting the next import'
+ end
+ end
+
+ context 'migrations are disabled' do
+ before do
+ allow(ContainerRegistry::Migration).to receive(:enabled?).and_return(false)
+ end
+
+ it_behaves_like 'no action' do
+ before do
+ expect_log_extra_metadata(migration_enabled: false)
+ end
+ end
end
context 'above capacity' do
before do
- allow(ContainerRegistry::Migration).to receive(:capacity).and_return(-1)
+ create(:container_repository, :importing)
+ create(:container_repository, :importing)
+ allow(ContainerRegistry::Migration).to receive(:capacity).and_return(1)
+ end
+
+ it_behaves_like 'no action' do
+ before do
+ expect_log_extra_metadata(below_capacity: false, max_capacity_setting: 1)
+ end
end
it 'does not re-enqueue the worker' do
- expect(described_class).not_to receive(:perform_async)
- expect(described_class).not_to receive(:perform_in).with(7.seconds)
+ expect(ContainerRegistry::Migration::EnqueuerWorker).not_to receive(:perform_async)
+ expect(ContainerRegistry::Migration::EnqueuerWorker).not_to receive(:perform_in)
subject
end
end
- end
- context 'with qualified repository' do
- before do
- method = worker.method(:next_repository)
- allow(worker).to receive(:next_repository) do
- next_qualified_repository = method.call
- allow(next_qualified_repository).to receive(:migration_pre_import).and_return(:ok)
- next_qualified_repository
+ context 'too soon before previous completed import step' do
+ where(:state, :timestamp) do
+ :import_done | :migration_import_done_at
+ :pre_import_done | :migration_pre_import_done_at
+ :import_aborted | :migration_aborted_at
+ :import_skipped | :migration_skipped_at
+ end
+
+ with_them do
+ before do
+ allow(ContainerRegistry::Migration).to receive(:enqueue_waiting_time).and_return(45.minutes)
+ create(:container_repository, state, timestamp => 1.minute.ago)
+ end
+
+ it_behaves_like 'no action' do
+ before do
+ expect_log_extra_metadata(waiting_time_passed: false, current_waiting_time_setting: 45.minutes)
+ end
+ end
+ end
+
+ context 'when last completed repository has nil timestamps' do
+ before do
+ allow(ContainerRegistry::Migration).to receive(:enqueue_waiting_time).and_return(45.minutes)
+ create(:container_repository, migration_state: 'import_done')
+ end
+
+ it 'continues to try the next import' do
+ expect { subject }.to change { container_repository.reload.migration_state }
+ end
+ end
+ end
+
+ context 'when an aborted import is available' do
+ let_it_be(:aborted_repository) { create(:container_repository, :import_aborted) }
+
+ context 'with a successful registry request' do
+ before do
+ allow_worker(on: :next_aborted_repository) do |repository|
+ allow(repository).to receive(:migration_import).and_return(:ok)
+ allow(repository.gitlab_api_client).to receive(:import_status).and_return('import_failed')
+ end
+ end
+
+ it 'retries the import for the aborted repository' do
+ expect_log_extra_metadata(
+ import_type: 'retry',
+ container_repository_id: aborted_repository.id,
+ container_repository_path: aborted_repository.path,
+ container_repository_migration_state: 'importing'
+ )
+
+ subject
+
+ expect(aborted_repository.reload).to be_importing
+ expect(container_repository.reload).to be_default
+ end
+
+ it_behaves_like 're-enqueuing based on capacity'
+ end
+
+ context 'when an error occurs' do
+ it 'does not abort that migration' do
+ allow_worker(on: :next_aborted_repository) do |repository|
+ allow(repository).to receive(:retry_aborted_migration).and_raise(StandardError)
+ end
+
+ expect_log_extra_metadata(
+ import_type: 'retry',
+ container_repository_id: aborted_repository.id,
+ container_repository_path: aborted_repository.path,
+ container_repository_migration_state: 'import_aborted'
+ )
+
+ subject
+
+ expect(aborted_repository.reload).to be_import_aborted
+ expect(container_repository.reload).to be_default
+ end
+ end
+ end
+
+ context 'when no repository qualifies' do
+ include_examples 'an idempotent worker' do
+ before do
+ allow(ContainerRepository).to receive(:ready_for_import).and_return(ContainerRepository.none)
+ end
+
+ it_behaves_like 'no action'
end
end
- shared_examples 'starting the next import' do
- it 'starts the pre-import for the next qualified repository' do
+ context 'over max tag count' do
+ before do
+ stub_application_setting(container_registry_import_max_tags_count: 2)
+ end
+
+ it 'skips the repository' do
expect_log_extra_metadata(
import_type: 'next',
container_repository_id: container_repository.id,
container_repository_path: container_repository.path,
- container_repository_migration_state: 'pre_importing'
+ container_repository_migration_state: 'import_skipped',
+ tags_count_too_high: true,
+ max_tags_count_setting: 2
)
subject
- expect(container_repository.reload).to be_pre_importing
+ expect(container_repository.reload).to be_import_skipped
+ expect(container_repository.migration_skipped_reason).to eq('too_many_tags')
+ expect(container_repository.migration_skipped_at).not_to be_nil
end
- end
- it_behaves_like 'starting the next import'
+ context 're-enqueuing' do
+ before do
+ # skipping will also re-enqueue, so we isolate the capacity behavior here
+ allow_worker(on: :next_repository) do |repository|
+ allow(repository).to receive(:skip_import).and_return(true)
+ end
+ end
+
+ it_behaves_like 're-enqueuing based on capacity', capacity_limit: 3
+ end
+ end
- context 'when the new pre-import maxes out the capacity' do
+ context 'when an error occurs' do
before do
- # set capacity to 10
- stub_feature_flags(
- container_registry_migration_phase2_capacity_25: false
- )
-
- # Plus 2 created above gives 9 importing repositories
- create_list(:container_repository, 7, :importing)
+ allow(ContainerRegistry::Migration).to receive(:max_tags_count).and_raise(StandardError)
end
- it 'does not re-enqueue the worker' do
- expect(described_class).not_to receive(:perform_async)
- expect(described_class).not_to receive(:perform_in)
+ it 'aborts the import' do
+ expect_log_extra_metadata(
+ import_type: 'next',
+ container_repository_id: container_repository.id,
+ container_repository_path: container_repository.path,
+ container_repository_migration_state: 'import_aborted'
+ )
+
+ expect(Gitlab::ErrorTracking).to receive(:log_exception).with(
+ instance_of(StandardError),
+ next_repository_id: container_repository.id
+ )
subject
+
+ expect(container_repository.reload).to be_import_aborted
end
end
- it_behaves_like 're-enqueuing based on capacity'
+ context 'with the exclusive lease taken' do
+ let(:lease_key) { worker.send(:lease_key) }
- context 'max tag count is 0' do
before do
- stub_application_setting(container_registry_import_max_tags_count: 0)
- # Add 8 tags to the next repository
- stub_container_registry_tags(
- repository: container_repository.path, tags: %w(a b c d e f g h), with_manifest: true
- )
+ stub_exclusive_lease_taken(lease_key, timeout: 30.minutes)
end
- it_behaves_like 'starting the next import'
- end
- end
+ it 'does not perform' do
+ expect(worker).not_to receive(:runnable?)
+ expect(worker).not_to receive(:re_enqueue_if_capacity)
- context 'migrations are disabled' do
- before do
- allow(ContainerRegistry::Migration).to receive(:enabled?).and_return(false)
+ subject
+ end
end
+ end
- it_behaves_like 'no action' do
+ context 'with container_registry_migration_phase2_enqueuer_loop enabled' do
+ context 'migrations are disabled' do
before do
- expect_log_extra_metadata(migration_enabled: false)
+ allow(ContainerRegistry::Migration).to receive(:enabled?).and_return(false)
+ end
+
+ it_behaves_like 'no action' do
+ before do
+ expect_log_extra_metadata(migration_enabled: false)
+ end
end
end
- end
- context 'above capacity' do
- before do
- create(:container_repository, :importing)
- create(:container_repository, :importing)
- allow(ContainerRegistry::Migration).to receive(:capacity).and_return(1)
+ context 'with no repository qualifies' do
+ include_examples 'an idempotent worker' do
+ before do
+ allow(ContainerRepository).to receive(:ready_for_import).and_return(ContainerRepository.none)
+ end
+
+ it_behaves_like 'no action'
+ end
end
- it_behaves_like 'no action' do
+ context 'when multiple aborted imports are available' do
+ let_it_be(:aborted_repository1) { create(:container_repository, :import_aborted) }
+ let_it_be(:aborted_repository2) { create(:container_repository, :import_aborted) }
+
before do
- expect_log_extra_metadata(below_capacity: false, max_capacity_setting: 1)
+ container_repository.update!(created_at: 30.seconds.ago)
end
- end
- it 'does not re-enqueue the worker' do
- expect(ContainerRegistry::Migration::EnqueuerWorker).not_to receive(:perform_async)
- expect(ContainerRegistry::Migration::EnqueuerWorker).not_to receive(:perform_in)
+ context 'with successful registry requests' do
+ before do
+ allow_worker(on: :next_aborted_repository) do |repository|
+ allow(repository).to receive(:migration_import).and_return(:ok)
+ allow(repository.gitlab_api_client).to receive(:import_status).and_return('import_failed')
+ end
+ end
- subject
- end
- end
+ it 'retries the import for the aborted repository' do
+ expect_log_info(
+ [
+ {
+ import_type: 'retry',
+ container_repository_id: aborted_repository1.id,
+ container_repository_path: aborted_repository1.path,
+ container_repository_migration_state: 'importing'
+ },
+ {
+ import_type: 'retry',
+ container_repository_id: aborted_repository2.id,
+ container_repository_path: aborted_repository2.path,
+ container_repository_migration_state: 'importing'
+ }
+ ]
+ )
+
+ expect(worker).to receive(:handle_next_migration).and_call_original
- context 'too soon before previous completed import step' do
- where(:state, :timestamp) do
- :import_done | :migration_import_done_at
- :pre_import_done | :migration_pre_import_done_at
- :import_aborted | :migration_aborted_at
- :import_skipped | :migration_skipped_at
+ subject
+
+ expect(aborted_repository1.reload).to be_importing
+ expect(aborted_repository2.reload).to be_importing
+ end
+ end
+
+ context 'when an error occurs' do
+ it 'does abort that migration' do
+ allow_worker(on: :next_aborted_repository) do |repository|
+ allow(repository).to receive(:retry_aborted_migration).and_raise(StandardError)
+ end
+
+ expect_log_info(
+ [
+ {
+ import_type: 'retry',
+ container_repository_id: aborted_repository1.id,
+ container_repository_path: aborted_repository1.path,
+ container_repository_migration_state: 'import_aborted'
+ }
+ ]
+ )
+
+ subject
+
+ expect(aborted_repository1.reload).to be_import_aborted
+ expect(aborted_repository2.reload).to be_import_aborted
+ end
+ end
end
- with_them do
+ context 'when multiple qualified repositories are available' do
+ let_it_be(:container_repository2) { create(:container_repository, created_at: 2.days.ago) }
+
before do
- allow(ContainerRegistry::Migration).to receive(:enqueue_waiting_time).and_return(45.minutes)
- create(:container_repository, state, timestamp => 1.minute.ago)
+ allow_worker(on: :next_repository) do |repository|
+ allow(repository).to receive(:migration_pre_import).and_return(:ok)
+ end
+
+ stub_container_registry_tags(
+ repository: container_repository2.path,
+ tags: %w(tag4 tag5 tag6),
+ with_manifest: true
+ )
end
- it_behaves_like 'no action' do
+ shared_examples 'starting all the next imports' do
+ it 'starts the pre-import for the next qualified repositories' do
+ expect_log_info(
+ [
+ {
+ import_type: 'next',
+ container_repository_id: container_repository.id,
+ container_repository_path: container_repository.path,
+ container_repository_migration_state: 'pre_importing'
+ },
+ {
+ import_type: 'next',
+ container_repository_id: container_repository2.id,
+ container_repository_path: container_repository2.path,
+ container_repository_migration_state: 'pre_importing'
+ }
+ ]
+ )
+
+ expect(worker).to receive(:handle_next_migration).exactly(3).times.and_call_original
+
+ subject
+
+ expect(container_repository.reload).to be_pre_importing
+ expect(container_repository2.reload).to be_pre_importing
+ end
+ end
+
+ it_behaves_like 'starting all the next imports'
+
+ context 'when the new pre-import maxes out the capacity' do
before do
- expect_log_extra_metadata(waiting_time_passed: false, current_waiting_time_setting: 45.minutes)
+ # set capacity to 10
+ stub_feature_flags(
+ container_registry_migration_phase2_capacity_25: false
+ )
+
+ # Plus 2 created above gives 9 importing repositories
+ create_list(:container_repository, 7, :importing)
+ end
+
+ it 'starts the pre-import only for one qualified repository' do
+ expect_log_info(
+ [
+ {
+ import_type: 'next',
+ container_repository_id: container_repository.id,
+ container_repository_path: container_repository.path,
+ container_repository_migration_state: 'pre_importing'
+ }
+ ]
+ )
+
+ subject
+
+ expect(container_repository.reload).to be_pre_importing
+ expect(container_repository2.reload).to be_default
end
end
- end
- context 'when last completed repository has nil timestamps' do
- before do
- allow(ContainerRegistry::Migration).to receive(:enqueue_waiting_time).and_return(45.minutes)
- create(:container_repository, migration_state: 'import_done')
+ context 'max tag count is 0' do
+ before do
+ stub_application_setting(container_registry_import_max_tags_count: 0)
+ # Add 8 tags to the next repository
+ stub_container_registry_tags(
+ repository: container_repository.path, tags: %w(a b c d e f g h), with_manifest: true
+ )
+ end
+
+ it_behaves_like 'starting all the next imports'
end
- it 'continues to try the next import' do
- expect { subject }.to change { container_repository.reload.migration_state }
+ context 'when the deadline is hit' do
+ it 'does not handle the second qualified repository' do
+ expect(worker).to receive(:loop_deadline).and_return(5.seconds.from_now, 2.seconds.ago)
+ expect(worker).to receive(:handle_next_migration).once.and_call_original
+
+ subject
+
+ expect(container_repository.reload).to be_pre_importing
+ expect(container_repository2.reload).to be_default
+ end
end
end
- end
- context 'when an aborted import is available' do
- let_it_be(:aborted_repository) { create(:container_repository, :import_aborted) }
+ context 'when a mix of aborted imports and qualified repositories are available' do
+ let_it_be(:aborted_repository) { create(:container_repository, :import_aborted) }
- context 'with a successful registry request' do
before do
- method = worker.method(:next_aborted_repository)
- allow(worker).to receive(:next_aborted_repository) do
- next_aborted_repository = method.call
- allow(next_aborted_repository).to receive(:migration_import).and_return(:ok)
- allow(next_aborted_repository.gitlab_api_client).to receive(:import_status).and_return('import_failed')
- next_aborted_repository
+ allow_worker(on: :next_aborted_repository) do |repository|
+ allow(repository).to receive(:migration_import).and_return(:ok)
+ allow(repository.gitlab_api_client).to receive(:import_status).and_return('import_failed')
+ end
+
+ allow_worker(on: :next_repository) do |repository|
+ allow(repository).to receive(:migration_pre_import).and_return(:ok)
end
end
- it 'retries the import for the aborted repository' do
- expect_log_extra_metadata(
- import_type: 'retry',
- container_repository_id: aborted_repository.id,
- container_repository_path: aborted_repository.path,
- container_repository_migration_state: 'importing'
+ it 'retries the aborted repository and start the migration on the qualified repository' do
+ expect_log_info(
+ [
+ {
+ import_type: 'retry',
+ container_repository_id: aborted_repository.id,
+ container_repository_path: aborted_repository.path,
+ container_repository_migration_state: 'importing'
+ },
+ {
+ import_type: 'next',
+ container_repository_id: container_repository.id,
+ container_repository_path: container_repository.path,
+ container_repository_migration_state: 'pre_importing'
+ }
+ ]
)
subject
expect(aborted_repository.reload).to be_importing
- expect(container_repository.reload).to be_default
+ expect(container_repository.reload).to be_pre_importing
end
+ end
- it_behaves_like 're-enqueuing based on capacity'
+ context 'above capacity' do
+ before do
+ create(:container_repository, :importing)
+ create(:container_repository, :importing)
+ allow(ContainerRegistry::Migration).to receive(:capacity).and_return(1)
+ end
+
+ it_behaves_like 'no action' do
+ before do
+ expect_log_extra_metadata(below_capacity: false, max_capacity_setting: 1)
+ end
+ end
end
- context 'when an error occurs' do
- it 'does not abort that migration' do
- method = worker.method(:next_aborted_repository)
- allow(worker).to receive(:next_aborted_repository) do
- next_aborted_repository = method.call
- allow(next_aborted_repository).to receive(:retry_aborted_migration).and_raise(StandardError)
- next_aborted_repository
+ context 'too soon before previous completed import step' do
+ where(:state, :timestamp) do
+ :import_done | :migration_import_done_at
+ :pre_import_done | :migration_pre_import_done_at
+ :import_aborted | :migration_aborted_at
+ :import_skipped | :migration_skipped_at
+ end
+
+ with_them do
+ before do
+ allow(ContainerRegistry::Migration).to receive(:enqueue_waiting_time).and_return(45.minutes)
+ create(:container_repository, state, timestamp => 1.minute.ago)
end
- expect_log_extra_metadata(
- import_type: 'retry',
- container_repository_id: aborted_repository.id,
- container_repository_path: aborted_repository.path,
- container_repository_migration_state: 'import_aborted'
- )
+ it_behaves_like 'no action' do
+ before do
+ expect_log_extra_metadata(waiting_time_passed: false, current_waiting_time_setting: 45.minutes)
+ end
+ end
+ end
- subject
+ context 'when last completed repository has nil timestamps' do
+ before do
+ allow(ContainerRegistry::Migration).to receive(:enqueue_waiting_time).and_return(45.minutes)
+ create(:container_repository, migration_state: 'import_done')
+ end
- expect(aborted_repository.reload).to be_import_aborted
- expect(container_repository.reload).to be_default
+ it 'continues to try the next import' do
+ expect { subject }.to change { container_repository.reload.migration_state }
+ end
end
end
- end
- context 'when no repository qualifies' do
- include_examples 'an idempotent worker' do
+ context 'over max tag count' do
before do
- allow(ContainerRepository).to receive(:ready_for_import).and_return(ContainerRepository.none)
+ stub_application_setting(container_registry_import_max_tags_count: 2)
end
- it_behaves_like 'no action'
- end
- end
-
- context 'over max tag count' do
- before do
- stub_application_setting(container_registry_import_max_tags_count: 2)
- end
+ it 'skips the repository' do
+ expect_log_info(
+ [
+ {
+ import_type: 'next',
+ container_repository_id: container_repository.id,
+ container_repository_path: container_repository.path,
+ container_repository_migration_state: 'import_skipped',
+ container_repository_migration_skipped_reason: 'too_many_tags'
+ }
+ ]
+ )
- it 'skips the repository' do
- expect_log_extra_metadata(
- import_type: 'next',
- container_repository_id: container_repository.id,
- container_repository_path: container_repository.path,
- container_repository_migration_state: 'import_skipped',
- tags_count_too_high: true,
- max_tags_count_setting: 2
- )
+ expect(worker).to receive(:handle_next_migration).twice.and_call_original
+ # skipping the migration will re_enqueue the job
+ expect(described_class).to receive(:enqueue_a_job)
- subject
+ subject
- expect(container_repository.reload).to be_import_skipped
- expect(container_repository.migration_skipped_reason).to eq('too_many_tags')
- expect(container_repository.migration_skipped_at).not_to be_nil
+ expect(container_repository.reload).to be_import_skipped
+ expect(container_repository.migration_skipped_reason).to eq('too_many_tags')
+ expect(container_repository.migration_skipped_at).not_to be_nil
+ end
end
- context 're-enqueuing' do
+ context 'when an error occurs' do
before do
- # skipping will also re-enqueue, so we isolate the capacity behavior here
- method = worker.method(:next_repository)
- allow(worker).to receive(:next_repository) do
- next_qualified_repository = method.call
- allow(next_qualified_repository).to receive(:skip_import).and_return(true)
- next_qualified_repository
- end
+ allow(ContainerRegistry::Migration).to receive(:max_tags_count).and_raise(StandardError)
end
- it_behaves_like 're-enqueuing based on capacity', capacity_limit: 3
- end
- end
-
- context 'when an error occurs' do
- before do
- allow(ContainerRegistry::Migration).to receive(:max_tags_count).and_raise(StandardError)
- end
+ it 'aborts the import' do
+ expect_log_info(
+ [
+ {
+ import_type: 'next',
+ container_repository_id: container_repository.id,
+ container_repository_path: container_repository.path,
+ container_repository_migration_state: 'import_aborted'
+ }
+ ]
+ )
- it 'aborts the import' do
- expect_log_extra_metadata(
- import_type: 'next',
- container_repository_id: container_repository.id,
- container_repository_path: container_repository.path,
- container_repository_migration_state: 'import_aborted'
- )
+ expect(Gitlab::ErrorTracking).to receive(:log_exception).with(
+ instance_of(StandardError),
+ next_repository_id: container_repository.id
+ )
- expect(Gitlab::ErrorTracking).to receive(:log_exception).with(
- instance_of(StandardError),
- next_repository_id: container_repository.id
- )
+ # aborting the migration will re_enqueue the job
+ expect(described_class).to receive(:enqueue_a_job)
- subject
+ subject
- expect(container_repository.reload).to be_import_aborted
+ expect(container_repository.reload).to be_import_aborted
+ end
end
- end
- context 'with the exclusive lease taken' do
- let(:lease_key) { worker.send(:lease_key) }
+ context 'with the exclusive lease taken' do
+ let(:lease_key) { worker.send(:lease_key) }
- before do
- stub_exclusive_lease_taken(lease_key, timeout: 30.minutes)
- end
+ before do
+ stub_exclusive_lease_taken(lease_key, timeout: 30.minutes)
+ end
- it 'does not perform' do
- expect(worker).not_to receive(:runnable?)
- expect(worker).not_to receive(:re_enqueue_if_capacity)
+ it 'does not perform' do
+ expect(worker).not_to receive(:handle_aborted_migration)
+ expect(worker).not_to receive(:handle_next_migration)
- subject
+ subject
+ end
end
end
@@ -343,6 +694,23 @@ RSpec.describe ContainerRegistry::Migration::EnqueuerWorker, :aggregate_failures
expect(worker).to receive(:log_extra_metadata_on_done).with(key, value)
end
end
+
+ def expect_log_info(expected_multiple_arguments)
+ expected_multiple_arguments.each do |extras|
+ expect(worker.logger).to receive(:info).with(worker.structured_payload(extras))
+ end
+ end
+
+ def allow_worker(on:)
+ method_repository = worker.method(on)
+ allow(worker).to receive(on) do
+ repository = method_repository.call
+
+ yield repository if repository
+
+ repository
+ end
+ end
end
describe 'worker attributes' do
diff --git a/yarn.lock b/yarn.lock
index 542e28571c8..1ac64b3119c 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2571,7 +2571,7 @@ ansi-colors@^4.1.1:
resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348"
integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==
-ansi-escapes@^4.1.0, ansi-escapes@^4.2.1:
+ansi-escapes@^4.2.1:
version "4.3.2"
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e"
integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==
@@ -2583,11 +2583,6 @@ ansi-html-community@^0.0.8:
resolved "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41"
integrity sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==
-ansi-regex@^2.0.0:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
- integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8=
-
ansi-regex@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997"
@@ -2598,11 +2593,6 @@ ansi-regex@^5.0.0, ansi-regex@^5.0.1:
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
-ansi-styles@^2.2.1:
- version "2.2.1"
- resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
- integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=
-
ansi-styles@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
@@ -2645,13 +2635,6 @@ apollo-upload-client@15.0.0:
dependencies:
extract-files "^10.0.0"
-app-path@^3.2.0:
- version "3.3.0"
- resolved "https://registry.yarnpkg.com/app-path/-/app-path-3.3.0.tgz#0342a909db37079c593979c720f99e872475eba3"
- integrity sha512-EAgEXkdcxH1cgEePOSsmUtw9ItPl0KTxnh/pj9ZbhvbKbij9x0oX6PWpGnorDr0DS5AosLgoa5n3T/hZmKQpYA==
- dependencies:
- execa "^1.0.0"
-
aproba@^1.1.1:
version "1.2.0"
resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
@@ -2952,7 +2935,7 @@ balanced-match@^2.0.0:
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-2.0.0.tgz#dc70f920d78db8b858535795867bf48f820633d9"
integrity sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==
-base64-js@^1.0.2, base64-js@^1.3.1, base64-js@^1.5.1:
+base64-js@^1.0.2, base64-js@^1.3.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
@@ -3390,17 +3373,6 @@ chalk@4.1.2, chalk@^4.0.0, chalk@^4.1.0:
ansi-styles "^4.1.0"
supports-color "^7.1.0"
-chalk@^1.1.3:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
- integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=
- dependencies:
- ansi-styles "^2.2.1"
- escape-string-regexp "^1.0.2"
- has-ansi "^2.0.0"
- strip-ansi "^3.0.0"
- supports-color "^2.0.0"
-
chalk@^2.0.0, chalk@^2.1.0, chalk@^2.4.1, chalk@^2.4.2:
version "2.4.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
@@ -4141,18 +4113,6 @@ cyclist@~0.2.2:
resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640"
integrity sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=
-cypress-image-snapshot@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/cypress-image-snapshot/-/cypress-image-snapshot-4.0.1.tgz#59084e713a8d03500c8e053ad7a76f3f18609648"
- integrity sha512-PBpnhX/XItlx3/DAk5ozsXQHUi72exybBNH5Mpqj1DVmjq+S5Jd9WE5CRa4q5q0zuMZb2V2VpXHth6MjFpgj9Q==
- dependencies:
- chalk "^2.4.1"
- fs-extra "^7.0.1"
- glob "^7.1.3"
- jest-image-snapshot "4.2.0"
- pkg-dir "^3.0.0"
- term-img "^4.0.0"
-
d3-array@1, "d3-array@1 - 2", d3-array@^1.1.1, d3-array@^1.2.0:
version "1.2.4"
resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-1.2.4.tgz#635ce4d5eea759f6f605863dbcfc30edc737f71f"
@@ -5024,10 +4984,10 @@ dompurify@2.3.6:
resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.3.6.tgz#2e019d7d7617aacac07cbbe3d88ae3ad354cf875"
integrity sha512-OFP2u/3T1R5CEgWCEONuJ1a5+MFKnOYpkywpUSxv/dj1LeBT1erK+JwM7zK0ROy2BRhqVCf0LRw/kHqKuMkVGg==
-dompurify@^2.3.7:
- version "2.3.7"
- resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.3.7.tgz#30aa7feddc1420f3e554b1b3fe9e2f318a28066e"
- integrity sha512-fsVZLywBd3awZIG3qU4JEdw7DCb0uUCajTfWRrLhsgKjTBd5CIIluPoAkNfco05GuNYQGj4/+bQIhlq96eT9eQ==
+dompurify@^2.3.7, dompurify@^2.3.8:
+ version "2.3.8"
+ resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.3.8.tgz#224fe9ae57d7ebd9a1ae1ac18c1c1ca3f532226f"
+ integrity sha512-eVhaWoVibIzqdGYjwsBWodIQIaXFSB+cKDf4cfxLMsK0xiud6SE+/WCVx/Xw/UwQsa4cS3T2eITcdtmTg2UKcw==
domutils@^2.5.2, domutils@^2.6.0:
version "2.6.0"
@@ -5281,7 +5241,7 @@ escape-html@~1.0.3:
resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=
-escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5, escape-string-regexp@~1.0.5:
+escape-string-regexp@^1.0.5, escape-string-regexp@~1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
@@ -6075,15 +6035,6 @@ from2@^2.1.0:
inherits "^2.0.1"
readable-stream "^2.0.0"
-fs-extra@^7.0.1:
- version "7.0.1"
- resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9"
- integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==
- dependencies:
- graceful-fs "^4.1.2"
- jsonfile "^4.0.0"
- universalify "^0.1.0"
-
fs-minipass@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.0.0.tgz#a6415edab02fae4b9e9230bc87ee2e4472003cd1"
@@ -6155,11 +6106,6 @@ get-package-type@^0.1.0:
resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a"
integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==
-get-stdin@^5.0.1:
- version "5.0.1"
- resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398"
- integrity sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g=
-
get-stdin@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b"
@@ -6305,11 +6251,6 @@ globjoin@^0.1.4:
resolved "https://registry.yarnpkg.com/globjoin/-/globjoin-0.1.4.tgz#2f4494ac8919e3767c5cbb691e9f463324285d43"
integrity sha1-L0SUrIkZ43Z8XLtpHp9GMyQoXUM=
-glur@^1.1.2:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/glur/-/glur-1.1.2.tgz#f20ea36db103bfc292343921f1f91e83c3467689"
- integrity sha1-8g6jbbEDv8KSNDkh8fkeg8NGdok=
-
good-listener@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/good-listener/-/good-listener-1.2.2.tgz#d53b30cdf9313dffb7dc9a0d477096aa6d145c50"
@@ -6334,7 +6275,7 @@ got@^9.6.0:
to-readable-stream "^1.0.0"
url-parse-lax "^3.0.0"
-graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.4, graceful-fs@^4.2.6:
+graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.9, graceful-fs@^4.2.4, graceful-fs@^4.2.6:
version "4.2.10"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c"
integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==
@@ -6432,13 +6373,6 @@ hard-rejection@^2.1.0:
resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883"
integrity sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==
-has-ansi@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
- integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=
- dependencies:
- ansi-regex "^2.0.0"
-
has-flag@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
@@ -7355,14 +7289,6 @@ iterall@^1.2.1:
resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.3.0.tgz#afcb08492e2915cbd8a0884eb93a8c94d0d72fea"
integrity sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg==
-iterm2-version@^4.1.0:
- version "4.2.0"
- resolved "https://registry.yarnpkg.com/iterm2-version/-/iterm2-version-4.2.0.tgz#b78069f747f34a772bc7dc17bda5bd9ed5e09633"
- integrity sha512-IoiNVk4SMPu6uTcK+1nA5QaHNok2BMDLjSl5UomrOixe5g4GkylhPwuiGdw00ysSCrXAKNMfFTu+u/Lk5f6OLQ==
- dependencies:
- app-path "^3.2.0"
- plist "^3.0.1"
-
jed@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/jed/-/jed-1.1.1.tgz#7a549bbd9ffe1585b0cd0a191e203055bee574b4"
@@ -7522,21 +7448,6 @@ jest-haste-map@^26.5.2:
optionalDependencies:
fsevents "^2.1.2"
-jest-image-snapshot@4.2.0:
- version "4.2.0"
- resolved "https://registry.yarnpkg.com/jest-image-snapshot/-/jest-image-snapshot-4.2.0.tgz#559d7ade69e9918517269cef184261c80029a69e"
- integrity sha512-6aAqv2wtfOgxiJeBayBCqHo1zX+A12SUNNzo7rIxiXh6W6xYVu8QyHWkada8HeRi+QUTHddp0O0Xa6kmQr+xbQ==
- dependencies:
- chalk "^1.1.3"
- get-stdin "^5.0.1"
- glur "^1.1.2"
- lodash "^4.17.4"
- mkdirp "^0.5.1"
- pixelmatch "^5.1.0"
- pngjs "^3.4.0"
- rimraf "^2.6.2"
- ssim.js "^3.1.1"
-
jest-jasmine2@^26.5.2:
version "26.5.2"
resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-26.5.2.tgz#0e33819d31b1f2aab5efd1e02ce502209c0e64a2"
@@ -7989,13 +7900,6 @@ jsonc-parser@~3.0.0:
resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.0.0.tgz#abdd785701c7e7eaca8a9ec8cf070ca51a745a22"
integrity sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==
-jsonfile@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
- integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=
- optionalDependencies:
- graceful-fs "^4.1.6"
-
jsprim@^1.2.2:
version "1.4.1"
resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
@@ -8036,10 +7940,10 @@ keyv@^3.0.0:
dependencies:
json-buffer "3.0.0"
-khroma@^1.4.1:
- version "1.4.1"
- resolved "https://registry.yarnpkg.com/khroma/-/khroma-1.4.1.tgz#ad6a5b6a972befc5112ce5129887a1a83af2c003"
- integrity sha512-+GmxKvmiRuCcUYDgR7g5Ngo0JEDeOsGdNONdU2zsiBQaK4z19Y2NvXqfEDE0ZiIrg45GTZyAnPLVsLZZACYm3Q==
+khroma@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/khroma/-/khroma-2.0.0.tgz#7577de98aed9f36c7a474c4d453d94c0d6c6588b"
+ integrity sha512-2J8rDNlQWbtiNYThZRvmMv5yt44ZakX+Tz5ZIp/mN1pt4snn+m030Va5Z4v8xA0cQFDXBwO/8i42xL4QPsVk3g==
kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0:
version "3.2.2"
@@ -8337,7 +8241,7 @@ lodash.values@^4.3.0:
resolved "https://registry.yarnpkg.com/lodash.values/-/lodash.values-4.3.0.tgz#a3a6c2b0ebecc5c2cba1c17e6e620fe81b53d347"
integrity sha1-o6bCsOvsxcLLocF+bmIP6BtT00c=
-lodash@^4.17.10, lodash@^4.17.13, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4:
+lodash@^4.17.10, lodash@^4.17.13, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
@@ -8649,19 +8553,18 @@ merge2@^1.3.0, merge2@^1.4.1:
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
-mermaid@^9.0.1:
- version "9.0.1"
- resolved "https://registry.yarnpkg.com/mermaid/-/mermaid-9.0.1.tgz#b804f372d827936ab8a8cbde72a5b79fb2629680"
- integrity sha512-TXXffALLhCACez+MUky4cOOcGXEXiJhHwN8eRV7bBqD8F6KdcjssyPZClVgzrC2KQzSGLqQkj7ce8ea7MhWz+Q==
+mermaid@^9.1.1:
+ version "9.1.1"
+ resolved "https://registry.yarnpkg.com/mermaid/-/mermaid-9.1.1.tgz#5d3d330ca4adf7f3c8ca51095f8bb2f0fb1a93bb"
+ integrity sha512-2RVD+WkzZ4VDyO9gQvQAuQ/ux2gLigJtKDTlbwjYqOR/NwsVzTSfGm/kx648/qWJsg6Sv04tE9BWCO8s6a+pFA==
dependencies:
"@braintree/sanitize-url" "^6.0.0"
- cypress-image-snapshot "^4.0.1"
d3 "^7.0.0"
dagre "^0.8.5"
dagre-d3 "^0.6.4"
dompurify "2.3.6"
graphlib "^2.1.8"
- khroma "^1.4.1"
+ khroma "^2.0.0"
moment-mini "^2.24.0"
stylis "^4.0.10"
@@ -9855,13 +9758,6 @@ pirates@^4.0.1:
dependencies:
node-modules-regexp "^1.0.0"
-pixelmatch@^5.1.0:
- version "5.2.1"
- resolved "https://registry.yarnpkg.com/pixelmatch/-/pixelmatch-5.2.1.tgz#9e4e4f4aa59648208a31310306a5bed5522b0d65"
- integrity sha512-WjcAdYSnKrrdDdqTcVEY7aB7UhhwjYQKYhHiBXdJef0MOaQeYpUdQ+iVyBLa5YBKS8MPVPPMX7rpOByISLpeEQ==
- dependencies:
- pngjs "^4.0.1"
-
pkg-dir@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b"
@@ -9883,29 +9779,11 @@ pkg-dir@^4.1.0, pkg-dir@^4.2.0:
dependencies:
find-up "^4.0.0"
-plist@^3.0.1:
- version "3.0.5"
- resolved "https://registry.yarnpkg.com/plist/-/plist-3.0.5.tgz#2cbeb52d10e3cdccccf0c11a63a85d830970a987"
- integrity sha512-83vX4eYdQp3vP9SxuYgEM/G/pJQqLUz/V/xzPrzruLs7fz7jxGQ1msZ/mg1nwZxUSuOp4sb+/bEIbRrbzZRxDA==
- dependencies:
- base64-js "^1.5.1"
- xmlbuilder "^9.0.7"
-
pluralize@^8.0.0:
version "8.0.0"
resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1"
integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==
-pngjs@^3.4.0:
- version "3.4.0"
- resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.4.0.tgz#99ca7d725965fb655814eaf65f38f12bbdbf555f"
- integrity sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==
-
-pngjs@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-4.0.1.tgz#f803869bb2fc1bfe1bf99aa4ec21c108117cfdbe"
- integrity sha512-rf5+2/ioHeQxR6IxuYNYGFytUyG3lma/WW1nsmjeHlWwtb2aByla6dkVc8pmJ9nplzkTA0q2xx7mMWrOTqT4Gg==
-
pofile@1.0.x:
version "1.0.11"
resolved "https://registry.yarnpkg.com/pofile/-/pofile-1.0.11.tgz#35aff58c17491d127a07336d5522ebc9df57c954"
@@ -10808,7 +10686,7 @@ reusify@^1.0.4:
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
-rimraf@^2.5.4, rimraf@^2.6.2, rimraf@^2.6.3:
+rimraf@^2.5.4, rimraf@^2.6.3:
version "2.7.1"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==
@@ -11418,11 +11296,6 @@ sshpk@^1.7.0:
safer-buffer "^2.0.2"
tweetnacl "~0.14.0"
-ssim.js@^3.1.1:
- version "3.5.0"
- resolved "https://registry.yarnpkg.com/ssim.js/-/ssim.js-3.5.0.tgz#d7276b9ee99b57a5ff0db34035f02f35197e62df"
- integrity sha512-Aj6Jl2z6oDmgYFFbQqK7fght19bXdOxY7Tj03nF+03M9gCBAjeIiO8/PlEGMfKDwYpw4q6iBqVq2YuREorGg/g==
-
ssri@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.1.tgz#2a3c41b28dd45b62b63676ecb74001265ae9edd8"
@@ -11558,13 +11431,6 @@ string_decoder@~0.10.x:
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=
-strip-ansi@^3.0.0:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
- integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=
- dependencies:
- ansi-regex "^2.0.0"
-
strip-ansi@^5.1.0, strip-ansi@^5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae"
@@ -11717,11 +11583,6 @@ subscriptions-transport-ws@^0.11.0:
symbol-observable "^1.0.4"
ws "^5.2.0 || ^6.0.0 || ^7.0.0"
-supports-color@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
- integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=
-
supports-color@^5.3.0, supports-color@^5.5.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
@@ -11820,14 +11681,6 @@ tar@^6.0.2:
mkdirp "^1.0.3"
yallist "^4.0.0"
-term-img@^4.0.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/term-img/-/term-img-4.1.0.tgz#5b170961f7aa20b2f3b22deb8ad504beb963a8a5"
- integrity sha512-DFpBhaF5j+2f7kheKFc1ajsAUUDGOaNPpKPtiIMxlbfud6mvfFZuWGnTRpaujUa5J7yl6cIw/h6nyr4mSsENPg==
- dependencies:
- ansi-escapes "^4.1.0"
- iterm2-version "^4.1.0"
-
term-size@^2.1.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/term-size/-/term-size-2.2.0.tgz#1f16adedfe9bdc18800e1776821734086fcc6753"
@@ -12367,11 +12220,6 @@ unist-util-visit@^4.0.0:
unist-util-is "^5.0.0"
unist-util-visit-parents "^5.0.0"
-universalify@^0.1.0:
- version "0.1.2"
- resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
- integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
-
unixify@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/unixify/-/unixify-1.0.0.tgz#3a641c8c2ffbce4da683a5c70f03a462940c2090"
@@ -13165,7 +13013,7 @@ xml@^1.0.1:
resolved "https://registry.yarnpkg.com/xml/-/xml-1.0.1.tgz#78ba72020029c5bc87b8a81a3cfcd74b4a2fc1e5"
integrity sha1-eLpyAgApxbyHuKgaPPzXS0ovweU=
-xmlbuilder@^9.0.7, xmlbuilder@~9.0.1:
+xmlbuilder@~9.0.1:
version "9.0.7"
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d"
integrity sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=