summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.rubocop_manual_todo.yml278
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--Gemfile1
-rw-r--r--Gemfile.lock4
-rw-r--r--app/assets/javascripts/behaviors/gl_emoji.js1
-rw-r--r--app/assets/javascripts/invite_members/components/invite_members_modal.vue4
-rw-r--r--app/assets/javascripts/issuable_list/components/issuable_item.vue4
-rw-r--r--app/assets/javascripts/members/components/table/role_dropdown.vue2
-rw-r--r--app/graphql/mutations/snippets/create.rb2
-rw-r--r--app/graphql/mutations/snippets/update.rb2
-rw-r--r--app/models/concerns/issuable.rb2
-rw-r--r--app/models/concerns/time_trackable.rb18
-rw-r--r--app/models/preloaders/user_max_access_level_in_projects_preloader.rb2
-rw-r--r--app/services/authorized_project_update/project_group_link_create_service.rb2
-rw-r--r--app/services/ci/update_build_state_service.rb10
-rw-r--r--app/services/issuable_base_service.rb1
-rw-r--r--app/services/snippets/base_service.rb6
-rw-r--r--app/services/snippets/create_service.rb2
-rw-r--r--app/services/snippets/update_service.rb2
-rw-r--r--app/views/shared/members/_group.html.haml2
-rw-r--r--app/views/shared/members/_invite_group.html.haml4
-rw-r--r--app/views/shared/members/_invite_member.html.haml4
-rw-r--r--app/views/shared/members/_member.html.haml2
-rw-r--r--app/workers/all_queues.yml2
-rw-r--r--app/workers/pipeline_hooks_worker.rb2
-rw-r--r--config/feature_flags/development/load_balancing_for_pipeline_hooks_worker.yml8
-rw-r--r--doc/administration/reference_architectures/10k_users.md86
-rw-r--r--doc/administration/reference_architectures/25k_users.md37
-rw-r--r--doc/administration/reference_architectures/2k_users.md20
-rw-r--r--doc/administration/reference_architectures/3k_users.md29
-rw-r--r--doc/administration/reference_architectures/50k_users.md37
-rw-r--r--doc/administration/reference_architectures/5k_users.md29
-rw-r--r--doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md13
-rw-r--r--doc/api/broadcast_messages.md4
-rw-r--r--doc/api/invitations.md2
-rw-r--r--doc/ci/runners/README.md3
-rw-r--r--doc/ci/triggers/README.md2
-rw-r--r--doc/development/testing_guide/best_practices.md30
-rw-r--r--doc/user/admin_area/settings/continuous_integration.md2
-rw-r--r--doc/user/group/index.md4
-rw-r--r--doc/user/project/integrations/webhooks.md2
-rw-r--r--doc/user/project/members/share_project_with_groups.md2
-rw-r--r--lib/api/concerns/packages/conan_endpoints.rb2
-rw-r--r--lib/api/generic_packages.rb4
-rw-r--r--lib/api/helpers/packages/conan/api_helpers.rb4
-rw-r--r--lib/api/project_snippets.rb4
-rw-r--r--lib/api/snippets.rb4
-rw-r--r--lib/gitlab/experimentation/controller_concern.rb2
-rw-r--r--lib/gitlab/hook_data/issue_builder.rb3
-rw-r--r--lib/gitlab/hook_data/merge_request_builder.rb3
-rw-r--r--lib/gitlab/time_tracking_formatter.rb10
-rw-r--r--locale/gitlab.pot27
-rw-r--r--package.json1
-rw-r--r--rubocop/cop/rspec/have_enqueued_sidekiq_job.rb60
-rw-r--r--spec/frontend/members/components/table/role_dropdown_spec.js2
-rw-r--r--spec/lib/gitlab/ci/config/entry/job_spec.rb4
-rw-r--r--spec/lib/gitlab/database/postgres_index_spec.rb6
-rw-r--r--spec/lib/gitlab/experimentation/controller_concern_spec.rb21
-rw-r--r--spec/lib/gitlab/hook_data/issue_builder_spec.rb2
-rw-r--r--spec/lib/gitlab/hook_data/merge_request_builder_spec.rb2
-rw-r--r--spec/lib/gitlab/time_tracking_formatter_spec.rb6
-rw-r--r--spec/models/ci/build_spec.rb18
-rw-r--r--spec/models/concerns/issuable_spec.rb14
-rw-r--r--spec/requests/api/conan_instance_packages_spec.rb2
-rw-r--r--spec/requests/api/generic_packages_spec.rb1
-rw-r--r--spec/requests/api/graphql/mutations/snippets/create_spec.rb4
-rw-r--r--spec/requests/api/graphql/mutations/snippets/update_spec.rb2
-rw-r--r--spec/rubocop/cop/rspec/have_enqueued_sidekiq_job_spec.rb51
-rw-r--r--spec/services/ci/update_build_state_service_spec.rb18
-rw-r--r--spec/services/merge_requests/update_service_spec.rb1
-rw-r--r--spec/services/snippets/create_service_spec.rb2
-rw-r--r--spec/services/snippets/update_service_spec.rb2
-rw-r--r--spec/support/shared_examples/graphql/mutations/can_mutate_spammable_examples.rb6
-rw-r--r--spec/support/shared_examples/requests/api/tracking_shared_examples.rb2
-rw-r--r--spec/workers/pipeline_hooks_worker_spec.rb5
-rw-r--r--yarn.lock12
76 files changed, 765 insertions, 213 deletions
diff --git a/.rubocop_manual_todo.yml b/.rubocop_manual_todo.yml
index 5992affe96a..a847fbfe22b 100644
--- a/.rubocop_manual_todo.yml
+++ b/.rubocop_manual_todo.yml
@@ -1354,6 +1354,284 @@ RSpec/AnyInstanceOf:
- 'spec/workers/wait_for_cluster_creation_worker_spec.rb'
- 'ee/spec/workers/security/auto_fix_worker_spec.rb'
+# WIP: https://gitlab.com/gitlab-org/gitlab/-/issues/331835
+RSpec/HaveEnqueuedSidekiqJob:
+ Exclude:
+ - 'ee/spec/lib/gitlab/geo/log_cursor/events/job_artifact_deleted_event_spec.rb'
+ - 'ee/spec/lib/gitlab/geo/log_cursor/events/repository_deleted_event_spec.rb'
+ - 'ee/spec/lib/gitlab/geo/log_cursor/events/repository_renamed_event_spec.rb'
+ - 'ee/spec/lib/gitlab/geo/log_cursor/events/repository_updated_event_spec.rb'
+ - 'ee/spec/models/ci/pipeline_spec.rb'
+ - 'ee/spec/models/concerns/elastic/project_wiki_spec.rb'
+ - 'ee/spec/models/concerns/elastic/projects_search_spec.rb'
+ - 'ee/spec/models/ee/alert_management/alert_spec.rb'
+ - 'ee/spec/models/ee/user_spec.rb'
+ - 'ee/spec/models/elasticsearch_indexed_namespace_spec.rb'
+ - 'ee/spec/models/elasticsearch_indexed_project_spec.rb'
+ - 'ee/spec/models/gitlab/seat_link_data_spec.rb'
+ - 'ee/spec/models/group_wiki_spec.rb'
+ - 'ee/spec/models/namespace_statistics_spec.rb'
+ - 'ee/spec/models/project_feature_spec.rb'
+ - 'ee/spec/models/project_import_state_spec.rb'
+ - 'ee/spec/models/project_spec.rb'
+ - 'ee/spec/requests/api/elasticsearch_indexed_namespaces_spec.rb'
+ - 'ee/spec/requests/api/graphql/mutations/requirements_management/export_requirements_spec.rb'
+ - 'ee/spec/requests/api/project_mirror_spec.rb'
+ - 'ee/spec/requests/api/projects_spec.rb'
+ - 'ee/spec/services/admin/email_service_spec.rb'
+ - 'ee/spec/services/application_settings/update_service_spec.rb'
+ - 'ee/spec/services/auto_merge/merge_train_service_spec.rb'
+ - 'ee/spec/services/ci_cd/github_setup_service_spec.rb'
+ - 'ee/spec/services/dast_site_validations/create_service_spec.rb'
+ - 'ee/spec/services/ee/git/branch_push_service_spec.rb'
+ - 'ee/spec/services/ee/merge_requests/handle_assignees_change_service_spec.rb'
+ - 'ee/spec/services/ee/merge_requests/update_service_spec.rb'
+ - 'ee/spec/services/elastic/process_initial_bookkeeping_service_spec.rb'
+ - 'ee/spec/services/epics/update_dates_service_spec.rb'
+ - 'ee/spec/services/geo/container_repository_sync_service_spec.rb'
+ - 'ee/spec/services/geo/design_repository_sync_service_spec.rb'
+ - 'ee/spec/services/geo/framework_repository_sync_service_spec.rb'
+ - 'ee/spec/services/geo/hashed_storage_attachments_migration_service_spec.rb'
+ - 'ee/spec/services/geo/hashed_storage_migration_service_spec.rb'
+ - 'ee/spec/services/geo/project_housekeeping_service_spec.rb'
+ - 'ee/spec/services/geo/rename_repository_service_spec.rb'
+ - 'ee/spec/services/geo/repository_destroy_service_spec.rb'
+ - 'ee/spec/services/groups/transfer_service_spec.rb'
+ - 'ee/spec/services/milestones/destroy_service_spec.rb'
+ - 'ee/spec/services/projects/transfer_service_spec.rb'
+ - 'ee/spec/services/security/store_report_service_spec.rb'
+ - 'ee/spec/services/status_page/trigger_publish_service_spec.rb'
+ - 'ee/spec/services/web_hook_service_spec.rb'
+ - 'ee/spec/support/shared_examples/models/concerns/verifiable_replicator_shared_examples.rb'
+ - 'ee/spec/support/shared_examples/quick_actions/issue/status_page_quick_actions_shared_examples.rb'
+ - 'ee/spec/support/shared_examples/services/base_sync_service_shared_examples.rb'
+ - 'ee/spec/support/shared_examples/status_page/trigger_publish_shared_examples.rb'
+ - 'ee/spec/workers/build_finished_worker_spec.rb'
+ - 'ee/spec/workers/elastic_remove_expired_namespace_subscriptions_from_index_cron_worker_spec.rb'
+ - 'ee/spec/workers/geo/container_repository_sync_dispatch_worker_spec.rb'
+ - 'ee/spec/workers/geo/design_repository_shard_sync_worker_spec.rb'
+ - 'ee/spec/workers/geo/file_download_dispatch_worker_spec.rb'
+ - 'ee/spec/workers/geo/registry_sync_worker_spec.rb'
+ - 'ee/spec/workers/geo/repositories_clean_up_worker_spec.rb'
+ - 'ee/spec/workers/geo/repository_shard_sync_worker_spec.rb'
+ - 'ee/spec/workers/geo/repository_verification/primary/batch_worker_spec.rb'
+ - 'ee/spec/workers/geo/repository_verification/primary/shard_worker_spec.rb'
+ - 'ee/spec/workers/geo/repository_verification/secondary/scheduler_worker_spec.rb'
+ - 'ee/spec/workers/geo/repository_verification/secondary/shard_worker_spec.rb'
+ - 'ee/spec/workers/geo/secondary/registry_consistency_worker_spec.rb'
+ - 'ee/spec/workers/incident_management/oncall_rotations/persist_all_rotations_shifts_job_spec.rb'
+ - 'ee/spec/workers/post_receive_spec.rb'
+ - 'ee/spec/workers/store_security_reports_worker_spec.rb'
+ - 'ee/spec/workers/sync_seat_link_worker_spec.rb'
+ - 'spec/controllers/admin/clusters_controller_spec.rb'
+ - 'spec/controllers/admin/services_controller_spec.rb'
+ - 'spec/controllers/chaos_controller_spec.rb'
+ - 'spec/controllers/groups/clusters_controller_spec.rb'
+ - 'spec/controllers/groups_controller_spec.rb'
+ - 'spec/controllers/projects/clusters_controller_spec.rb'
+ - 'spec/controllers/projects/issues_controller_spec.rb'
+ - 'spec/controllers/projects/merge_requests_controller_spec.rb'
+ - 'spec/controllers/projects/pipeline_schedules_controller_spec.rb'
+ - 'spec/controllers/projects/registry/repositories_controller_spec.rb'
+ - 'spec/controllers/projects/settings/ci_cd_controller_spec.rb'
+ - 'spec/controllers/repositories/git_http_controller_spec.rb'
+ - 'spec/features/admin/admin_uses_repository_checks_spec.rb'
+ - 'spec/features/clusters/installing_applications_shared_examples.rb'
+ - 'spec/features/issues/csv_spec.rb'
+ - 'spec/graphql/mutations/container_repositories/destroy_spec.rb'
+ - 'spec/graphql/mutations/merge_requests/accept_spec.rb'
+ - 'spec/lib/gitlab/ci/pipeline/chain/pipeline/process_spec.rb'
+ - 'spec/lib/gitlab/cleanup/orphan_lfs_file_references_spec.rb'
+ - 'spec/lib/gitlab/database/migrations/background_migration_helpers_spec.rb'
+ - 'spec/lib/gitlab/github_import/importer/diff_notes_importer_spec.rb'
+ - 'spec/lib/gitlab/github_import/importer/issues_importer_spec.rb'
+ - 'spec/lib/gitlab/github_import/importer/lfs_objects_importer_spec.rb'
+ - 'spec/lib/gitlab/github_import/importer/notes_importer_spec.rb'
+ - 'spec/lib/gitlab/github_import/importer/pull_requests_importer_spec.rb'
+ - 'spec/lib/gitlab/jira_import/issues_importer_spec.rb'
+ - 'spec/lib/gitlab/pages_transfer_spec.rb'
+ - 'spec/models/abuse_report_spec.rb'
+ - 'spec/models/ci/build_spec.rb'
+ - 'spec/models/ci/build_trace_chunk_spec.rb'
+ - 'spec/models/ci/job_artifact_spec.rb'
+ - 'spec/models/ci/pipeline_spec.rb'
+ - 'spec/models/ci/processable_spec.rb'
+ - 'spec/models/clusters/integrations/prometheus_spec.rb'
+ - 'spec/models/commit_status_spec.rb'
+ - 'spec/models/concerns/reactive_caching_spec.rb'
+ - 'spec/models/deployment_spec.rb'
+ - 'spec/models/diff_note_spec.rb'
+ - 'spec/models/integrations/emails_on_push_spec.rb'
+ - 'spec/models/issue_spec.rb'
+ - 'spec/models/jira_import_state_spec.rb'
+ - 'spec/models/key_spec.rb'
+ - 'spec/models/lfs_object_spec.rb'
+ - 'spec/models/lfs_objects_project_spec.rb'
+ - 'spec/models/merge_request_spec.rb'
+ - 'spec/models/namespace/aggregation_schedule_spec.rb'
+ - 'spec/models/namespace_spec.rb'
+ - 'spec/models/operations/feature_flag_spec.rb'
+ - 'spec/models/packages/package_spec.rb'
+ - 'spec/models/pages_domain_spec.rb'
+ - 'spec/models/pool_repository_spec.rb'
+ - 'spec/models/project_import_state_spec.rb'
+ - 'spec/models/project_services/prometheus_service_spec.rb'
+ - 'spec/models/project_spec.rb'
+ - 'spec/models/project_statistics_spec.rb'
+ - 'spec/models/project_wiki_spec.rb'
+ - 'spec/models/remote_mirror_spec.rb'
+ - 'spec/models/sentry_issue_spec.rb'
+ - 'spec/models/snippet_statistics_spec.rb'
+ - 'spec/models/user_spec.rb'
+ - 'spec/models/x509_certificate_spec.rb'
+ - 'spec/requests/api/dependency_proxy_spec.rb'
+ - 'spec/requests/api/graphql/mutations/container_repository/destroy_spec.rb'
+ - 'spec/requests/api/group_import_spec.rb'
+ - 'spec/requests/api/merge_requests_spec.rb'
+ - 'spec/requests/api/project_container_repositories_spec.rb'
+ - 'spec/requests/api/project_packages_spec.rb'
+ - 'spec/requests/lfs_http_spec.rb'
+ - 'spec/services/admin/propagate_integration_service_spec.rb'
+ - 'spec/services/admin/propagate_service_template_spec.rb'
+ - 'spec/services/application_settings/update_service_spec.rb'
+ - 'spec/services/auto_merge/merge_when_pipeline_succeeds_service_spec.rb'
+ - 'spec/services/branches/delete_merged_service_spec.rb'
+ - 'spec/services/branches/delete_service_spec.rb'
+ - 'spec/services/bulk_import_service_spec.rb'
+ - 'spec/services/bulk_imports/export_service_spec.rb'
+ - 'spec/services/ci/create_pipeline_service_spec.rb'
+ - 'spec/services/ci/list_config_variables_service_spec.rb'
+ - 'spec/services/ci/pipeline_schedule_service_spec.rb'
+ - 'spec/services/ci/play_bridge_service_spec.rb'
+ - 'spec/services/ci/test_failure_history_service_spec.rb'
+ - 'spec/services/ci/update_build_state_service_spec.rb'
+ - 'spec/services/clusters/applications/create_service_spec.rb'
+ - 'spec/services/clusters/applications/schedule_update_service_spec.rb'
+ - 'spec/services/clusters/applications/update_service_spec.rb'
+ - 'spec/services/clusters/cleanup/app_service_spec.rb'
+ - 'spec/services/clusters/cleanup/project_namespace_service_spec.rb'
+ - 'spec/services/clusters/create_service_spec.rb'
+ - 'spec/services/container_expiration_policy_service_spec.rb'
+ - 'spec/services/deployments/create_service_spec.rb'
+ - 'spec/services/design_management/delete_designs_service_spec.rb'
+ - 'spec/services/discussions/resolve_service_spec.rb'
+ - 'spec/services/feature_flags/create_service_spec.rb'
+ - 'spec/services/feature_flags/update_service_spec.rb'
+ - 'spec/services/git/branch_hooks_service_spec.rb'
+ - 'spec/services/git/branch_push_service_spec.rb'
+ - 'spec/services/git/tag_push_service_spec.rb'
+ - 'spec/services/grafana/proxy_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/incident_management/pager_duty/process_webhook_service_spec.rb'
+ - 'spec/services/issuable/bulk_update_service_spec.rb'
+ - 'spec/services/issues/create_service_spec.rb'
+ - 'spec/services/issues/update_service_spec.rb'
+ - 'spec/services/members/destroy_service_spec.rb'
+ - 'spec/services/merge_requests/handle_assignees_change_service_spec.rb'
+ - 'spec/services/merge_requests/merge_service_spec.rb'
+ - 'spec/services/merge_requests/mergeability_check_service_spec.rb'
+ - 'spec/services/merge_requests/resolve_todos_service_spec.rb'
+ - 'spec/services/metrics/dashboard/grafana_metric_embed_service_spec.rb'
+ - 'spec/services/notes/create_service_spec.rb'
+ - 'spec/services/notification_service_spec.rb'
+ - 'spec/services/onboarding_progress_service_spec.rb'
+ - 'spec/services/packages/composer/create_package_service_spec.rb'
+ - 'spec/services/packages/debian/process_changes_service_spec.rb'
+ - 'spec/services/packages/go/sync_packages_service_spec.rb'
+ - 'spec/services/pages/delete_service_spec.rb'
+ - 'spec/services/post_receive_service_spec.rb'
+ - 'spec/services/projects/after_rename_service_spec.rb'
+ - 'spec/services/projects/create_service_spec.rb'
+ - 'spec/services/projects/group_links/create_service_spec.rb'
+ - 'spec/services/projects/group_links/destroy_service_spec.rb'
+ - 'spec/services/projects/repository_languages_service_spec.rb'
+ - 'spec/services/projects/transfer_service_spec.rb'
+ - 'spec/services/projects/update_service_spec.rb'
+ - 'spec/services/prometheus/proxy_service_spec.rb'
+ - 'spec/services/resource_access_tokens/revoke_service_spec.rb'
+ - 'spec/services/snippets/destroy_service_spec.rb'
+ - 'spec/services/snippets/update_statistics_service_spec.rb'
+ - 'spec/services/tags/destroy_service_spec.rb'
+ - 'spec/services/todos/destroy/entity_leave_service_spec.rb'
+ - 'spec/services/web_hook_service_spec.rb'
+ - 'spec/support/services/clusters/create_service_shared.rb'
+ - 'spec/support/shared_examples/controllers/access_tokens_controller_shared_examples.rb'
+ - 'spec/support/shared_examples/models/update_project_statistics_shared_examples.rb'
+ - 'spec/support/shared_examples/requests/api/conan_packages_shared_examples.rb'
+ - 'spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb'
+ - 'spec/support/shared_examples/requests/api/nuget_packages_shared_examples.rb'
+ - 'spec/support/shared_examples/requests/api/rubygems_packages_shared_examples.rb'
+ - 'spec/support/shared_examples/services/alert_management/alert_processing/incident_creation_shared_examples.rb'
+ - 'spec/support/shared_examples/services/issuable/destroy_service_shared_examples.rb'
+ - 'spec/support/shared_examples/services/packages_shared_examples.rb'
+ - 'spec/support/shared_examples/workers/gitlab/jira_import/jira_import_workers_shared_examples.rb'
+ - 'spec/tasks/gitlab/storage_rake_spec.rb'
+ - 'spec/uploaders/external_diff_uploader_spec.rb'
+ - 'spec/uploaders/lfs_object_uploader_spec.rb'
+ - 'spec/workers/authorized_project_update/user_refresh_over_user_range_worker_spec.rb'
+ - 'spec/workers/build_finished_worker_spec.rb'
+ - 'spec/workers/bulk_import_worker_spec.rb'
+ - 'spec/workers/bulk_imports/entity_worker_spec.rb'
+ - 'spec/workers/bulk_imports/pipeline_worker_spec.rb'
+ - 'spec/workers/deployments/execute_hooks_worker_spec.rb'
+ - 'spec/workers/deployments/hooks_worker_spec.rb'
+ - 'spec/workers/export_csv_worker_spec.rb'
+ - 'spec/workers/gitlab/github_import/advance_stage_worker_spec.rb'
+ - 'spec/workers/gitlab/github_import/stage/import_base_data_worker_spec.rb'
+ - 'spec/workers/gitlab/github_import/stage/import_issues_and_diff_notes_worker_spec.rb'
+ - 'spec/workers/gitlab/github_import/stage/import_lfs_objects_worker_spec.rb'
+ - 'spec/workers/gitlab/github_import/stage/import_notes_worker_spec.rb'
+ - 'spec/workers/gitlab/github_import/stage/import_pull_requests_merged_by_worker_spec.rb'
+ - 'spec/workers/gitlab/github_import/stage/import_pull_requests_reviews_worker_spec.rb'
+ - 'spec/workers/gitlab/github_import/stage/import_pull_requests_worker_spec.rb'
+ - 'spec/workers/gitlab/github_import/stage/import_repository_worker_spec.rb'
+ - 'spec/workers/gitlab/jira_import/stage/start_import_worker_spec.rb'
+ - 'spec/workers/issue_placement_worker_spec.rb'
+ - 'spec/workers/metrics/dashboard/schedule_annotations_prune_worker_spec.rb'
+ - 'spec/workers/pages_domain_ssl_renewal_cron_worker_spec.rb'
+ - 'spec/workers/pages_domain_verification_cron_worker_spec.rb'
+ - 'spec/workers/post_receive_spec.rb'
+ - 'spec/workers/project_cache_worker_spec.rb'
+ - 'spec/workers/repository_check/dispatch_worker_spec.rb'
+ - 'ee/spec/lib/gitlab/geo/log_cursor/daemon_spec.rb'
+ - 'ee/spec/lib/gitlab/geo/log_cursor/events/repository_created_event_spec.rb'
+ - 'ee/spec/models/merge_train_spec.rb'
+ - 'ee/spec/services/iterations/cadences/create_service_spec.rb'
+ - 'ee/spec/workers/incident_management/incident_sla_exceeded_check_worker_spec.rb'
+ - 'ee/spec/workers/iterations/cadences/schedule_create_iterations_worker_spec.rb'
+ - 'spec/controllers/admin/clusters/applications_controller_spec.rb'
+ - 'spec/controllers/groups/clusters/applications_controller_spec.rb'
+ - 'spec/controllers/projects/clusters/applications_controller_spec.rb'
+ - 'spec/controllers/projects/mirrors_controller_spec.rb'
+ - 'spec/lib/gitlab/background_migration_spec.rb'
+ - 'spec/lib/gitlab/github_import/parallel_importer_spec.rb'
+ - 'spec/requests/api/ci/pipeline_schedules_spec.rb'
+ - 'spec/services/auto_merge/base_service_spec.rb'
+ - 'spec/services/git/process_ref_changes_service_spec.rb'
+ - 'spec/services/merge_requests/base_service_spec.rb'
+ - 'spec/services/web_hooks/destroy_service_spec.rb'
+ - 'spec/workers/container_expiration_policy_worker_spec.rb'
+ - 'spec/workers/namespaces/prune_aggregation_schedules_worker_spec.rb'
+ - 'ee/spec/services/elastic/indexing_control_service_spec.rb'
+ - 'ee/spec/support/shared_examples/lib/gitlab/geo/geo_log_cursor_event_shared_examples.rb'
+ - 'ee/spec/workers/geo/repository_sync_worker_spec.rb'
+ - 'ee/spec/workers/update_all_mirrors_worker_spec.rb'
+ - 'spec/lib/gitlab/github_import/parallel_scheduling_spec.rb'
+ - 'spec/models/clusters/cluster_spec.rb'
+ - 'spec/services/clusters/applications/destroy_service_spec.rb'
+ - 'spec/support/shared_examples/models/concerns/repository_storage_movable_shared_examples.rb'
+ - 'spec/support/shared_examples/requests/api/repository_storage_moves_shared_examples.rb'
+ - 'spec/support/shared_examples/requests/self_monitoring_shared_examples.rb'
+ - 'spec/support/shared_examples/services/repositories/housekeeping_shared_examples.rb'
+ - 'spec/support/shared_examples/services/schedule_bulk_repository_shard_moves_shared_examples.rb'
+ - 'spec/uploaders/workers/object_storage/migrate_uploads_worker_spec.rb'
+ - 'spec/workers/concerns/limited_capacity/worker_spec.rb'
+ - 'spec/workers/concerns/reenqueuer_spec.rb'
+ - 'spec/workers/gitlab/phabricator_import/base_worker_spec.rb'
+ - 'spec/workers/metrics/dashboard/prune_old_annotations_worker_spec.rb'
+
# WIP: https://gitlab.com/gitlab-org/gitlab/-/issues/321982
Gitlab/NamespacedClass:
Exclude:
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index 5cf4124a5bb..f658c634e50 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-dc956109aa3e352cadc55ebba267b43fdd4fdc27
+56c571a6bf20894de96f4739cfe17ede1befc8a2
diff --git a/Gemfile b/Gemfile
index d99cd5970e4..ffa901ed05c 100644
--- a/Gemfile
+++ b/Gemfile
@@ -432,6 +432,7 @@ group :test do
gem 'concurrent-ruby', '~> 1.1'
gem 'test-prof', '~> 0.12.0'
gem 'rspec_junit_formatter'
+ gem 'rspec-sidekiq'
gem 'guard-rspec'
# Moved in `test` because https://gitlab.com/gitlab-org/gitlab/-/issues/217527
diff --git a/Gemfile.lock b/Gemfile.lock
index a1fd31680a1..79ddfa796ba 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1090,6 +1090,9 @@ GEM
rspec-support (~> 3.10)
rspec-retry (0.6.1)
rspec-core (> 3.3)
+ rspec-sidekiq (3.1.0)
+ rspec-core (~> 3.0, >= 3.0.0)
+ sidekiq (>= 2.4.0)
rspec-support (3.10.2)
rspec_junit_formatter (0.4.1)
rspec-core (>= 2, < 4, != 2.12.0)
@@ -1605,6 +1608,7 @@ DEPENDENCIES
rspec-parameterized
rspec-rails (~> 5.0.1)
rspec-retry (~> 0.6.1)
+ rspec-sidekiq
rspec_junit_formatter
rspec_profiling (~> 0.0.6)
ruby-fogbugz (~> 0.2.1)
diff --git a/app/assets/javascripts/behaviors/gl_emoji.js b/app/assets/javascripts/behaviors/gl_emoji.js
index bf7a87144f9..ef445548e6e 100644
--- a/app/assets/javascripts/behaviors/gl_emoji.js
+++ b/app/assets/javascripts/behaviors/gl_emoji.js
@@ -1,4 +1,3 @@
-import 'document-register-element';
import {
initEmojiMap,
getEmojiInfo,
diff --git a/app/assets/javascripts/invite_members/components/invite_members_modal.vue b/app/assets/javascripts/invite_members/components/invite_members_modal.vue
index 6628fc4063b..0db464bb657 100644
--- a/app/assets/javascripts/invite_members/components/invite_members_modal.vue
+++ b/app/assets/javascripts/invite_members/components/invite_members_modal.vue
@@ -254,11 +254,11 @@ export default {
),
},
},
- accessLevel: s__('InviteMembersModal|Choose a role permission'),
+ accessLevel: s__('InviteMembersModal|Select a role'),
accessExpireDate: s__('InviteMembersModal|Access expiration date (optional)'),
toastMessageSuccessful: s__('InviteMembersModal|Members were successfully added'),
toastMessageUnsuccessful: s__('InviteMembersModal|Some of the members could not be added'),
- readMoreText: s__(`InviteMembersModal|%{linkStart}Read more%{linkEnd} about role permissions`),
+ readMoreText: s__(`InviteMembersModal|%{linkStart}Learn more%{linkEnd} about roles.`),
inviteButtonText: s__('InviteMembersModal|Invite'),
cancelButtonText: s__('InviteMembersModal|Cancel'),
headerCloseLabel: s__('InviteMembersModal|Close invite team members'),
diff --git a/app/assets/javascripts/issuable_list/components/issuable_item.vue b/app/assets/javascripts/issuable_list/components/issuable_item.vue
index 7635536c54f..348dc054f57 100644
--- a/app/assets/javascripts/issuable_list/components/issuable_item.vue
+++ b/app/assets/javascripts/issuable_list/components/issuable_item.vue
@@ -183,8 +183,8 @@ export default {
:title="__('Confidential')"
:aria-label="__('Confidential')"
/>
- <gl-link :href="webUrl" v-bind="issuableTitleProps"
- >{{ issuable.title
+ <gl-link :href="webUrl" v-bind="issuableTitleProps">
+ {{ issuable.title
}}<gl-icon v-if="isIssuableUrlExternal" name="external-link" class="gl-ml-2"
/></gl-link>
</span>
diff --git a/app/assets/javascripts/members/components/table/role_dropdown.vue b/app/assets/javascripts/members/components/table/role_dropdown.vue
index f84ded427cd..fa895cf24c4 100644
--- a/app/assets/javascripts/members/components/table/role_dropdown.vue
+++ b/app/assets/javascripts/members/components/table/role_dropdown.vue
@@ -78,7 +78,7 @@ export default {
ref="glDropdown"
:right="!isDesktop"
:text="member.accessLevel.stringValue"
- :header-text="__('Change permissions')"
+ :header-text="__('Change role')"
:disabled="disabled"
>
<gl-dropdown-item
diff --git a/app/graphql/mutations/snippets/create.rb b/app/graphql/mutations/snippets/create.rb
index e9b45294659..d1ad0697acd 100644
--- a/app/graphql/mutations/snippets/create.rb
+++ b/app/graphql/mutations/snippets/create.rb
@@ -49,7 +49,7 @@ module Mutations
process_args_for_params!(args)
- service_response = ::Snippets::CreateService.new(project, current_user, args).execute
+ service_response = ::Snippets::CreateService.new(project: project, current_user: current_user, params: args).execute
# Only when the user is not an api user and the operation was successful
if !api_user? && service_response.success?
diff --git a/app/graphql/mutations/snippets/update.rb b/app/graphql/mutations/snippets/update.rb
index b9b9b13eebb..2e1382e1cb1 100644
--- a/app/graphql/mutations/snippets/update.rb
+++ b/app/graphql/mutations/snippets/update.rb
@@ -34,7 +34,7 @@ module Mutations
process_args_for_params!(args)
- service_response = ::Snippets::UpdateService.new(snippet.project, current_user, args).execute(snippet)
+ service_response = ::Snippets::UpdateService.new(project: snippet.project, current_user: current_user, params: args).execute(snippet)
# TODO: DRY this up - From here down, this is all duplicated with Mutations::Snippets::Create#resolve, except for
# `snippet.reset`, which is required in order to return the object in its non-dirty, unmodified, database state
diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb
index b4289a0d131..2d06247a486 100644
--- a/app/models/concerns/issuable.rb
+++ b/app/models/concerns/issuable.rb
@@ -468,9 +468,11 @@ module Issuable
if self.respond_to?(:total_time_spent)
old_total_time_spent = old_associations.fetch(:total_time_spent, total_time_spent)
+ old_time_change = old_associations.fetch(:time_change, time_change)
if old_total_time_spent != total_time_spent
changes[:total_time_spent] = [old_total_time_spent, total_time_spent]
+ changes[:time_change] = [old_time_change, time_change]
end
end
end
diff --git a/app/models/concerns/time_trackable.rb b/app/models/concerns/time_trackable.rb
index a1e7d06b1c1..89b42eec727 100644
--- a/app/models/concerns/time_trackable.rb
+++ b/app/models/concerns/time_trackable.rb
@@ -33,11 +33,11 @@ module TimeTrackable
return if @time_spent == 0
- if @time_spent == :reset
- reset_spent_time
- else
- add_or_subtract_spent_time
- end
+ @timelog = if @time_spent == :reset
+ reset_spent_time
+ else
+ add_or_subtract_spent_time
+ end
end
alias_method :spend_time=, :spend_time
# rubocop:enable Gitlab/ModuleWithInstanceVariables
@@ -50,6 +50,14 @@ module TimeTrackable
Gitlab::TimeTrackingFormatter.output(total_time_spent)
end
+ def time_change
+ @timelog&.time_spent.to_i # rubocop:disable Gitlab/ModuleWithInstanceVariables
+ end
+
+ def human_time_change
+ Gitlab::TimeTrackingFormatter.output(time_change)
+ end
+
def human_time_estimate
Gitlab::TimeTrackingFormatter.output(time_estimate)
end
diff --git a/app/models/preloaders/user_max_access_level_in_projects_preloader.rb b/app/models/preloaders/user_max_access_level_in_projects_preloader.rb
index 671091480ee..c0ed56057ae 100644
--- a/app/models/preloaders/user_max_access_level_in_projects_preloader.rb
+++ b/app/models/preloaders/user_max_access_level_in_projects_preloader.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module Preloaders
- # This class preloads the max access level for the user within the given projects and
+ # This class preloads the max access level (role) for the user within the given projects and
# stores the values in requests store via the ProjectTeam class.
class UserMaxAccessLevelInProjectsPreloader
def initialize(projects, user)
diff --git a/app/services/authorized_project_update/project_group_link_create_service.rb b/app/services/authorized_project_update/project_group_link_create_service.rb
index 090b22a7820..e9e7c56d7c7 100644
--- a/app/services/authorized_project_update/project_group_link_create_service.rb
+++ b/app/services/authorized_project_update/project_group_link_create_service.rb
@@ -49,7 +49,7 @@ module AuthorizedProjectUpdate
def access_level(membership_access_level)
return membership_access_level unless group_access
- # access level must not be higher than the max access level set when
+ # access level (role) must not be higher than the max access level (role) set when
# creating the project share
[membership_access_level, group_access].min
end
diff --git a/app/services/ci/update_build_state_service.rb b/app/services/ci/update_build_state_service.rb
index 576300a64e6..abd50d2f110 100644
--- a/app/services/ci/update_build_state_service.rb
+++ b/app/services/ci/update_build_state_service.rb
@@ -169,7 +169,7 @@ module Ci
state: params.fetch(:state),
trace_checksum: trace_checksum,
trace_bytesize: trace_bytesize,
- failure_reason: params.dig(:failure_reason)
+ failure_reason: failure_reason
)
unless build_state.present?
@@ -179,6 +179,14 @@ module Ci
build_state || build.pending_state
end
+ def failure_reason
+ reason = params.dig(:failure_reason)
+
+ return unless reason
+
+ Ci::BuildPendingState.failure_reasons.fetch(reason.to_s, 'unknown_failure')
+ end
+
##
# This method is releasing an exclusive lock on a build trace the moment we
# conclude that build status has been written and the build state update
diff --git a/app/services/issuable_base_service.rb b/app/services/issuable_base_service.rb
index faa179618fc..1af23047db4 100644
--- a/app/services/issuable_base_service.rb
+++ b/app/services/issuable_base_service.rb
@@ -433,6 +433,7 @@ class IssuableBaseService < ::BaseProjectService
milestone: issuable.try(:milestone)
}
associations[:total_time_spent] = issuable.total_time_spent if issuable.respond_to?(:total_time_spent)
+ associations[:time_change] = issuable.time_change if issuable.respond_to?(:time_change)
associations[:description] = issuable.description
associations[:reviewers] = issuable.reviewers.to_a if issuable.allows_reviewers?
diff --git a/app/services/snippets/base_service.rb b/app/services/snippets/base_service.rb
index 415cfcb7d8f..1a04c4fcedd 100644
--- a/app/services/snippets/base_service.rb
+++ b/app/services/snippets/base_service.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module Snippets
- class BaseService < ::BaseService
+ class BaseService < ::BaseProjectService
UPDATE_COMMIT_MSG = 'Update snippet'
INITIAL_COMMIT_MSG = 'Initial commit'
@@ -9,7 +9,7 @@ module Snippets
attr_reader :uploaded_assets, :snippet_actions
- def initialize(project, user = nil, params = {})
+ def initialize(project: nil, current_user: nil, params: {})
super
@uploaded_assets = Array(@params.delete(:files).presence)
@@ -20,7 +20,7 @@ module Snippets
private
- def visibility_allowed?(snippet, visibility_level)
+ def visibility_allowed?(visibility_level)
Gitlab::VisibilityLevel.allowed_for?(current_user, visibility_level)
end
diff --git a/app/services/snippets/create_service.rb b/app/services/snippets/create_service.rb
index aadf9b865b8..8f1b481d307 100644
--- a/app/services/snippets/create_service.rb
+++ b/app/services/snippets/create_service.rb
@@ -12,7 +12,7 @@ module Snippets
return invalid_params_error(@snippet) unless valid_params?
- unless visibility_allowed?(snippet, snippet.visibility_level)
+ unless visibility_allowed?(snippet.visibility_level)
return forbidden_visibility_error(snippet)
end
diff --git a/app/services/snippets/update_service.rb b/app/services/snippets/update_service.rb
index 4088a08272d..8571bc9c869 100644
--- a/app/services/snippets/update_service.rb
+++ b/app/services/snippets/update_service.rb
@@ -14,7 +14,7 @@ module Snippets
return invalid_params_error(snippet) unless valid_params?
- if visibility_changed?(snippet) && !visibility_allowed?(snippet, visibility_level)
+ if visibility_changed?(snippet) && !visibility_allowed?(visibility_level)
return forbidden_visibility_error(snippet)
end
diff --git a/app/views/shared/members/_group.html.haml b/app/views/shared/members/_group.html.haml
index d98ba074687..2aac3a94c49 100644
--- a/app/views/shared/members/_group.html.haml
+++ b/app/views/shared/members/_group.html.haml
@@ -29,7 +29,7 @@
= group_link.human_access
= sprite_icon("chevron-down", css_class: "dropdown-menu-toggle-icon gl-top-3")
.dropdown-menu.dropdown-select.dropdown-menu-right.dropdown-menu-selectable
- = dropdown_title(_("Change permissions"))
+ = dropdown_title(_("Change role"))
.dropdown-content
%ul
- Gitlab::Access.options_with_owner.each do |role, role_id|
diff --git a/app/views/shared/members/_invite_group.html.haml b/app/views/shared/members/_invite_group.html.haml
index d8b4eb0a3a2..cefdf825eaa 100644
--- a/app/views/shared/members/_invite_group.html.haml
+++ b/app/views/shared/members/_invite_group.html.haml
@@ -14,14 +14,14 @@
.form-text.text-muted.gl-mb-3
= _('Group sharing provides access to all group members (including members who inherited group membership from a parent group).')
.form-group
- = label_tag group_access_field, _("Max access level"), class: "label-bold"
+ = label_tag group_access_field, _("Max role"), class: "label-bold"
.select-wrapper
= select_tag group_access_field, options_for_select(access_levels, default_access_level), data: { qa_selector: 'group_access_field' }, class: "form-control select-control"
= sprite_icon('chevron-down', css_class: "gl-icon gl-absolute gl-top-3 gl-right-3 gl-text-gray-200")
.form-text.text-muted.gl-mb-3
- permissions_docs_path = help_page_path('user/permissions')
- link_start = %q{<a href="%{url}">}.html_safe % { url: permissions_docs_path }
- = _("%{link_start}Read more%{link_end} about role permissions").html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
+ = _("%{link_start}Learn more%{link_end} about roles.").html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
.form-group
= label_tag :expires_at, _('Access expiration date'), class: 'label-bold'
.clearable-input
diff --git a/app/views/shared/members/_invite_member.html.haml b/app/views/shared/members/_invite_member.html.haml
index 49111c821b1..e6863ed56a5 100644
--- a/app/views/shared/members/_invite_member.html.haml
+++ b/app/views/shared/members/_invite_member.html.haml
@@ -10,14 +10,14 @@
= label_tag :user_ids, _("GitLab member or Email address"), class: "label-bold"
= users_select_tag(:user_ids, multiple: true, class: 'input-clamp qa-member-select-field', scope: :all, email_user: true, placeholder: 'Search for members to update or invite')
.form-group
- = label_tag :access_level, _("Choose a role permission"), class: "label-bold"
+ = label_tag :access_level, _("Select a role"), class: "label-bold"
.select-wrapper
= select_tag :access_level, options_for_select(access_levels, default_access_level), class: "form-control project-access-select select-control"
= sprite_icon('chevron-down', css_class: "gl-icon gl-absolute gl-top-3 gl-right-3 gl-text-gray-200")
.form-text.text-muted.gl-mb-3
- permissions_docs_path = help_page_path('user/permissions')
- link_start = %q{<a href="%{url}">}.html_safe % { url: permissions_docs_path }
- = _("%{link_start}Read more%{link_end} about role permissions").html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
+ = _("%{link_start}Learn more%{link_end} about roles.").html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
.form-group
= label_tag :expires_at, _('Access expiration date'), class: 'label-bold'
.clearable-input
diff --git a/app/views/shared/members/_member.html.haml b/app/views/shared/members/_member.html.haml
index 88e2a74d235..8f334be0427 100644
--- a/app/views/shared/members/_member.html.haml
+++ b/app/views/shared/members/_member.html.haml
@@ -81,7 +81,7 @@
= member.human_access
= sprite_icon("chevron-down", css_class: "dropdown-menu-toggle-icon gl-top-3")
.dropdown-menu.dropdown-select.dropdown-menu-right.dropdown-menu-selectable
- = dropdown_title(_("Change permissions"))
+ = dropdown_title(_("Change role"))
.dropdown-content
%ul
- member.valid_level_roles.each do |role, role_id|
diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml
index 8f6b795b2ed..59e6cd43325 100644
--- a/app/workers/all_queues.yml
+++ b/app/workers/all_queues.yml
@@ -1535,7 +1535,7 @@
:worker_name: PipelineHooksWorker
:feature_category: :continuous_integration
:has_external_dependencies:
- :urgency: :high
+ :urgency: :low
:resource_boundary: :cpu
:weight: 2
:idempotent:
diff --git a/app/workers/pipeline_hooks_worker.rb b/app/workers/pipeline_hooks_worker.rb
index fbb672f52e3..97e6adbbf18 100644
--- a/app/workers/pipeline_hooks_worker.rb
+++ b/app/workers/pipeline_hooks_worker.rb
@@ -7,8 +7,8 @@ class PipelineHooksWorker # rubocop:disable Scalability/IdempotentWorker
include PipelineQueue
queue_namespace :pipeline_hooks
- urgency :high
worker_resource_boundary :cpu
+ data_consistency :delayed, feature_flag: :load_balancing_for_pipeline_hooks_worker
# rubocop: disable CodeReuse/ActiveRecord
def perform(pipeline_id)
diff --git a/config/feature_flags/development/load_balancing_for_pipeline_hooks_worker.yml b/config/feature_flags/development/load_balancing_for_pipeline_hooks_worker.yml
new file mode 100644
index 00000000000..8e1794631f5
--- /dev/null
+++ b/config/feature_flags/development/load_balancing_for_pipeline_hooks_worker.yml
@@ -0,0 +1,8 @@
+---
+name: load_balancing_for_pipeline_hooks_worker
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62104
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/331424
+milestone: '14.0'
+type: development
+group: group::memory
+default_enabled: false
diff --git a/doc/administration/reference_architectures/10k_users.md b/doc/administration/reference_architectures/10k_users.md
index 454d9d33253..fe77285abc2 100644
--- a/doc/administration/reference_architectures/10k_users.md
+++ b/doc/administration/reference_architectures/10k_users.md
@@ -17,29 +17,34 @@ full list of reference architectures, see
| Service | Nodes | Configuration | GCP | AWS | Azure |
|--------------------------------------------|-------------|-------------------------|------------------|--------------|-----------|
-| External load balancing node | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Consul* | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| PostgreSQL* | 3 | 8 vCPU, 30 GB memory | `n1-standard-8` | `m5.2xlarge` | `D8s v3` |
-| PgBouncer* | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Internal load balancing node | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Redis - Cache** | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
-| Redis - Queues / Shared State** | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
-| Redis Sentinel - Cache** | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | `c5.large` | `A1 v2` |
-| Redis Sentinel - Queues / Shared State** | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | `c5.large` | `A1 v2` |
+| External load balancing node(3) | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| Consul(1) | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| PostgreSQL(1) | 3 | 8 vCPU, 30 GB memory | `n1-standard-8` | `m5.2xlarge` | `D8s v3` |
+| PgBouncer(1) | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| Internal load balancing node(3) | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| Redis - Cache(2) | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
+| Redis - Queues / Shared State(2) | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
+| Redis Sentinel - Cache(2) | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | `c5.large` | `A1 v2` |
+| Redis Sentinel - Queues / Shared State(2) | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | `c5.large` | `A1 v2` |
| Gitaly | 3 | 16 vCPU, 60 GB memory | `n1-standard-16` | `m5.4xlarge` | `D16s v3` |
| Praefect | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Praefect PostgreSQL* | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| Praefect PostgreSQL(1) | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Sidekiq | 4 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
| GitLab Rails | 3 | 32 vCPU, 28.8 GB memory | `n1-highcpu-32` | `c5.9xlarge` | `F32s v2` |
| Monitoring node | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
-| Object storage | n/a | n/a | n/a | n/a | n/a |
-| NFS server | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
+| Object storage(4) | n/a | n/a | n/a | n/a | n/a |
+| NFS server (optional, not recommended) | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
+
+<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
+<!-- markdownlint-disable MD029 -->
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
+2. Can be optionally run on reputable third-party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
+3. Can be optionally run on reputable third-party load balancing services (LB PaaS). AWS ELB is known to work.
+4. Should be run on reputable third party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
+<!-- markdownlint-enable MD029 -->
NOTE:
-Components marked with * can be optionally run on reputable
-third party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work.
-Components marked with ** can be optionally run on reputable
-third party external PaaS Redis solutions. Google Memorystore and AWS ElastiCache are known to work.
+For all PaaS solutions that involve configuring instances, it is strongly recommended to implement a minimum of three nodes in three different availability zones to align with resilient cloud architecture practices.
```plantuml
@startuml 10k
@@ -2398,35 +2403,46 @@ time use Google Cloud’s Kubernetes Engine (GKE) and associated machine types,
and CPU requirements should translate to most other providers. We hope to update this in the
future with further specific cloud provider details.
-| Service | Nodes | Configuration | GCP | Allocatable CPUs and Memory |
-|-------------------------------------------------------|-------|-------------------------|------------------|-----------------------------|
-| Webservice | 4 | 32 vCPU, 28.8 GB memory | `n1-highcpu-32` | 127.5 vCPU, 118 GB memory |
-| Sidekiq | 4 | 4 vCPU, 15 GB memory | `n1-standard-4` | 15.5 vCPU, 50 GB memory |
-| Supporting services such as NGINX, Prometheus, etc... | 2 | 4 vCPU, 15 GB memory | `n1-standard-4` | 7.75 vCPU, 25 GB memory |
+| Service | Nodes(1) | Configuration | GCP | Allocatable CPUs and Memory |
+|-------------------------------------------------------|----------|-------------------------|------------------|-----------------------------|
+| Webservice | 4 | 32 vCPU, 28.8 GB memory | `n1-highcpu-32` | 127.5 vCPU, 118 GB memory |
+| Sidekiq | 4 | 4 vCPU, 15 GB memory | `n1-standard-4` | 15.5 vCPU, 50 GB memory |
+| Supporting services such as NGINX, Prometheus, etc. | 2 | 4 vCPU, 15 GB memory | `n1-standard-4` | 7.75 vCPU, 25 GB memory |
+
+<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
+<!-- markdownlint-disable MD029 -->
+1. Nodes configuration is shown as it is forced to ensure pod vcpu / memory ratios and avoid scaling during **performance testing**.
+ In production deployments there is no need to assign pods to nodes. A minimum of three nodes in three different availability zones is strongly recommended to align with resilient cloud architecture practices.
+<!-- markdownlint-enable MD029 -->
Next are the backend components that run on static compute VMs via Omnibus (or External PaaS
services where applicable):
| Service | Nodes | Configuration | GCP |
|--------------------------------------------|-------|-------------------------|------------------|
-| Consul* | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
-| PostgreSQL* | 3 | 8 vCPU, 30 GB memory | `n1-standard-8` |
-| PgBouncer* | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
-| Internal load balancing node | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
-| Redis - Cache** | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` |
-| Redis - Queues / Shared State** | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` |
-| Redis Sentinel - Cache** | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` |
-| Redis Sentinel - Queues / Shared State** | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` |
+| Consul(1) | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
+| PostgreSQL(1) | 3 | 8 vCPU, 30 GB memory | `n1-standard-8` |
+| PgBouncer(1) | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
+| Internal load balancing node(3) | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
+| Redis - Cache(2) | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` |
+| Redis - Queues / Shared State(2) | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` |
+| Redis Sentinel - Cache(2) | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` |
+| Redis Sentinel - Queues / Shared State(2) | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` |
| Gitaly | 3 | 16 vCPU, 60 GB memory | `n1-standard-16` |
| Praefect | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
-| Praefect PostgreSQL* | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
-| Object storage | n/a | n/a | n/a |
+| Praefect PostgreSQL(1) | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
+| Object storage(4) | n/a | n/a | n/a |
+
+<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
+<!-- markdownlint-disable MD029 -->
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
+2. Can be optionally run on reputable third-party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
+3. Can be optionally run on reputable third-party load balancing services (LB PaaS). AWS ELB is known to work.
+4. Should be run on reputable third party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
+<!-- markdownlint-enable MD029 -->
NOTE:
-Components marked with * can be optionally run on reputable
-third party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work.
-Components marked with ** can be optionally run on reputable
-third party external PaaS Redis solutions. Google Memorystore and AWS ElastiCache are known to work.
+For all PaaS solutions that involve configuring instances, it is strongly recommended to implement a minimum of three nodes in three different availability zones to align with resilient cloud architecture practices.
```plantuml
@startuml 10k
diff --git a/doc/administration/reference_architectures/25k_users.md b/doc/administration/reference_architectures/25k_users.md
index 3826b06a350..df560b1c203 100644
--- a/doc/administration/reference_architectures/25k_users.md
+++ b/doc/administration/reference_architectures/25k_users.md
@@ -17,29 +17,34 @@ full list of reference architectures, see
| Service | Nodes | Configuration | GCP | AWS | Azure |
|------------------------------------------|-------------|-------------------------|------------------|--------------|-----------|
-| External load balancing node | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
-| Consul* | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| PostgreSQL* | 3 | 16 vCPU, 60 GB memory | `n1-standard-1` | `m5.4xlarge` | `D16s v3` |
-| PgBouncer* | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Internal load balancing node | 1 | 4 vCPU, 3.6GB memory | `n1-highcpu-4` | `c5.large` | `F2s v2` |
-| Redis - Cache** | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
-| Redis - Queues / Shared State** | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
-| Redis Sentinel - Cache** | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | `c5.large` | `A1 v2` |
-| Redis Sentinel - Queues / Shared State** | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | `c5.large` | `A1 v2` |
+| External load balancing node(3) | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
+| Consul(1) | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| PostgreSQL(1) | 3 | 16 vCPU, 60 GB memory | `n1-standard-1` | `m5.4xlarge` | `D16s v3` |
+| PgBouncer(1) | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| Internal load balancing node(3) | 1 | 4 vCPU, 3.6GB memory | `n1-highcpu-4` | `c5.large` | `F2s v2` |
+| Redis - Cache(2) | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
+| Redis - Queues / Shared State(2) | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
+| Redis Sentinel - Cache(2) | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | `c5.large` | `A1 v2` |
+| Redis Sentinel - Queues / Shared State(2)| 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | `c5.large` | `A1 v2` |
| Gitaly | 3 | 32 vCPU, 120 GB memory | `n1-standard-32` | `m5.8xlarge` | `D32s v3` |
| Praefect | 3 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
-| Praefect PostgreSQL* | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| Praefect PostgreSQL(1) | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Sidekiq | 4 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
| GitLab Rails | 5 | 32 vCPU, 28.8 GB memory | `n1-highcpu-32` | `c5.9xlarge` | `F32s v2` |
| Monitoring node | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
-| Object storage | n/a | n/a | n/a | n/a | n/a |
-| NFS server | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
+| Object storage(4) | n/a | n/a | n/a | n/a | n/a |
+| NFS server (optional, not recommended) | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
+
+<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
+<!-- markdownlint-disable MD029 -->
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
+2. Can be optionally run on reputable third-party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
+3. Can be optionally run on reputable third-party load balancing services (LB PaaS). AWS ELB is known to work.
+4. Should be run on reputable third party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
+<!-- markdownlint-enable MD029 -->
NOTE:
-Components marked with * can be optionally run on reputable
-third party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work.
-Components marked with ** can be optionally run on reputable
-third party external PaaS Redis solutions. Google Memorystore and AWS ElastiCache are known to work.
+For all PaaS solutions that involve configuring instances, it is strongly recommended to implement a minimum of three nodes in three different availability zones to align with resilient cloud architecture practices.
```plantuml
@startuml 25k
diff --git a/doc/administration/reference_architectures/2k_users.md b/doc/administration/reference_architectures/2k_users.md
index 1cd252cccd4..eea1812972b 100644
--- a/doc/administration/reference_architectures/2k_users.md
+++ b/doc/administration/reference_architectures/2k_users.md
@@ -18,20 +18,24 @@ For a full list of reference architectures, see
| Service | Nodes | Configuration | GCP | AWS | Azure |
|------------------------------------------|--------|-------------------------|-----------------|--------------|----------|
-| Load balancer | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| PostgreSQL* | 1 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | `m5.large` | `D2s v3` |
-| Redis** | 1 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | `m5.large` | `D2s v3` |
+| Load balancer(3) | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| PostgreSQL(1) | 1 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | `m5.large` | `D2s v3` |
+| Redis(2) | 1 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | `m5.large` | `D2s v3` |
| Gitaly | 1 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
| GitLab Rails | 2 | 8 vCPU, 7.2 GB memory | `n1-highcpu-8` | `c5.2xlarge` | `F8s v2` |
| Monitoring node | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Object storage | n/a | n/a | n/a | n/a | n/a |
+| Object storage(4) | n/a | n/a | n/a | n/a | n/a |
| NFS server (optional, not recommended) | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
+<!-- markdownlint-disable MD029 -->
+1. Can be optionally run on reputable third party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
+2. Can be optionally run as reputable third party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
+3. Can be optionally run as reputable third party load balancing services (LB PaaS). AWS ELB is known to work.
+4. Should be run on reputable third party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
+<!-- markdownlint-enable MD029 -->
+
NOTE:
-Components marked with * can be optionally run on reputable
-third party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work.
-Components marked with ** can be optionally run on reputable
-third party external PaaS Redis solutions. Google Memorystore and AWS ElastiCache are known to work.
+For all PaaS solutions that involve configuring instances, it is strongly recommended to implement a minimum of three nodes in three different availability zones to align with resilient cloud architecture practices.
```plantuml
@startuml 2k
diff --git a/doc/administration/reference_architectures/3k_users.md b/doc/administration/reference_architectures/3k_users.md
index a89e50396a7..b75f537ddbd 100644
--- a/doc/administration/reference_architectures/3k_users.md
+++ b/doc/administration/reference_architectures/3k_users.md
@@ -27,26 +27,31 @@ For a full list of reference architectures, see
| Service | Nodes | Configuration | GCP | AWS | Azure |
|--------------------------------------------|-------------|-----------------------|-----------------|--------------|----------|
-| External load balancing node | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Redis** | 3 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | `m5.large` | `D2s v3` |
-| Consul* + Sentinel** | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| PostgreSQL* | 3 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | `m5.large` | `D2s v3` |
-| PgBouncer* | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Internal load balancing node | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| External load balancing node(3) | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| Redis(2) | 3 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | `m5.large` | `D2s v3` |
+| Consul(1) + Sentinel(2) | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| PostgreSQL(1) | 3 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | `m5.large` | `D2s v3` |
+| PgBouncer(1) | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| Internal load balancing node(3) | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Gitaly | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
| Praefect | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Praefect PostgreSQL* | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| Praefect PostgreSQL(1) | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Sidekiq | 4 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | `m5.large` | `D2s v3` |
| GitLab Rails | 3 | 8 vCPU, 7.2 GB memory | `n1-highcpu-8` | `c5.2xlarge` | `F8s v2` |
| Monitoring node | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Object storage | n/a | n/a | n/a | n/a | n/a |
+| Object storage(4) | n/a | n/a | n/a | n/a | n/a |
| NFS server (optional, not recommended) | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
+<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
+<!-- markdownlint-disable MD029 -->
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
+2. Can be optionally run on reputable third-party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
+3. Can be optionally run on reputable third-party load balancing services (LB PaaS). AWS ELB is known to work.
+4. Should be run on reputable third party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
+<!-- markdownlint-enable MD029 -->
+
NOTE:
-Components marked with * can be optionally run on reputable
-third party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work.
-Components marked with ** can be optionally run on reputable
-third party external PaaS Redis solutions. Google Memorystore and AWS ElastiCache are known to work.
+For all PaaS solutions that involve configuring instances, it is strongly recommended to implement a minimum of three nodes in three different availability zones to align with resilient cloud architecture practices.
```plantuml
@startuml 3k
diff --git a/doc/administration/reference_architectures/50k_users.md b/doc/administration/reference_architectures/50k_users.md
index 272f6d4cadc..8986eea4026 100644
--- a/doc/administration/reference_architectures/50k_users.md
+++ b/doc/administration/reference_architectures/50k_users.md
@@ -17,29 +17,34 @@ full list of reference architectures, see
| Service | Nodes | Configuration | GCP | AWS | Azure |
|------------------------------------------|-------------|-------------------------|------------------|---------------|-----------|
-| External load balancing node | 1 | 8 vCPU, 7.2 GB memory | `n1-highcpu-8` | `c5.2xlarge` | `F8s v2` |
-| Consul* | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| PostgreSQL* | 3 | 32 vCPU, 120 GB memory | `n1-standard-32` | `m5.8xlarge` | `D32s v3` |
-| PgBouncer* | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Internal load balancing node | 1 | 8 vCPU, 7.2 GB memory | `n1-highcpu-8` | `c5.2xlarge` | `F8s v2` |
-| Redis - Cache** | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
-| Redis - Queues / Shared State** | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
-| Redis Sentinel - Cache** | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | `c5.large` | `A1 v2` |
-| Redis Sentinel - Queues / Shared State** | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | `c5.large` | `A1 v2` |
+| External load balancing node(3) | 1 | 8 vCPU, 7.2 GB memory | `n1-highcpu-8` | `c5.2xlarge` | `F8s v2` |
+| Consul(1) | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| PostgreSQL(1) | 3 | 32 vCPU, 120 GB memory | `n1-standard-32` | `m5.8xlarge` | `D32s v3` |
+| PgBouncer(1) | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| Internal load balancing node(3) | 1 | 8 vCPU, 7.2 GB memory | `n1-highcpu-8` | `c5.2xlarge` | `F8s v2` |
+| Redis - Cache(2) | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
+| Redis - Queues / Shared State(2) | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
+| Redis Sentinel - Cache(2) | 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | `c5.large` | `A1 v2` |
+| Redis Sentinel - Queues / Shared State(2)| 3 | 1 vCPU, 3.75 GB memory | `n1-standard-1` | `c5.large` | `A1 v2` |
| Gitaly | 3 | 64 vCPU, 240 GB memory | `n1-standard-64` | `m5.16xlarge` | `D64s v3` |
| Praefect | 3 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
-| Praefect PostgreSQL* | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| Praefect PostgreSQL(1) | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Sidekiq | 4 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
| GitLab Rails | 12 | 32 vCPU, 28.8 GB memory | `n1-highcpu-32` | `c5.9xlarge` | `F32s v2` |
| Monitoring node | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
-| Object storage | n/a | n/a | n/a | n/a | n/a |
-| NFS server | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
+| Object storage(4) | n/a | n/a | n/a | n/a | n/a |
+| NFS server (optional, not recommended) | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
+
+<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
+<!-- markdownlint-disable MD029 -->
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
+2. Can be optionally run on reputable third-party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
+3. Can be optionally run on reputable third-party load balancing services (LB PaaS). AWS ELB is known to work.
+4. Should be run on reputable third party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
+<!-- markdownlint-enable MD029 -->
NOTE:
-Components marked with * can be optionally run on reputable
-third party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work.
-Components marked with ** can be optionally run on reputable
-third party external PaaS Redis solutions. Google Memorystore and AWS ElastiCache are known to work.
+For all PaaS solutions that involve configuring instances, it is strongly recommended to implement a minimum of three nodes in three different availability zones to align with resilient cloud architecture practices.
```plantuml
@startuml 50k
diff --git a/doc/administration/reference_architectures/5k_users.md b/doc/administration/reference_architectures/5k_users.md
index 7ff28fbf477..784e8cd6f42 100644
--- a/doc/administration/reference_architectures/5k_users.md
+++ b/doc/administration/reference_architectures/5k_users.md
@@ -24,26 +24,31 @@ costly-to-operate environment by using the
| Service | Nodes | Configuration | GCP | AWS | Azure |
|--------------------------------------------|-------------|-------------------------|-----------------|--------------|----------|
-| External load balancing node | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Redis** | 3 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | `m5.large` | `D2s v3` |
-| Consul* + Sentinel** | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| PostgreSQL* | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
-| PgBouncer* | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Internal load balancing node | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| External load balancing node(3) | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| Redis(2) | 3 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | `m5.large` | `D2s v3` |
+| Consul(1) + Sentinel(2) | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| PostgreSQL(1) | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
+| PgBouncer(1) | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| Internal load balancing node(3) | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Gitaly | 3 | 8 vCPU, 30 GB memory | `n1-standard-8` | `m5.2xlarge` | `D8s v3` |
| Praefect | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Praefect PostgreSQL* | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
+| Praefect PostgreSQL(1) | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Sidekiq | 4 | 2 vCPU, 7.5 GB memory | `n1-standard-2` | `m5.large` | `D2s v3` |
| GitLab Rails | 3 | 16 vCPU, 14.4 GB memory | `n1-highcpu-16` | `c5.4xlarge` | `F16s v2`|
| Monitoring node | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
-| Object storage | n/a | n/a | n/a | n/a | n/a |
+| Object storage(4) | n/a | n/a | n/a | n/a | n/a |
| NFS server (optional, not recommended) | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
+<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
+<!-- markdownlint-disable MD029 -->
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
+2. Can be optionally run on reputable third-party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
+3. Can be optionally run on reputable third-party load balancing services (LB PaaS). AWS ELB is known to work.
+4. Should be run on reputable third party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
+<!-- markdownlint-enable MD029 -->
+
NOTE:
-Components marked with * can be optionally run on reputable
-third party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work.
-Components marked with ** can be optionally run on reputable
-third party external PaaS Redis solutions. Google Memorystore and AWS ElastiCache are known to work.
+For all PaaS solutions that involve configuring instances, it is strongly recommended to implement a minimum of three nodes in three different availability zones to align with resilient cloud architecture practices.
```plantuml
@startuml 5k
diff --git a/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md b/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md
index 35412fa0b0c..f05c1af836f 100644
--- a/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md
+++ b/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md
@@ -317,7 +317,18 @@ the displayed size may still show old sizes or commit numbers. To force an updat
p = Project.find_by_full_path('<namespace>/<project>')
pp p.statistics
p.statistics.refresh!
-pp p.statistics # compare with earlier values
+pp p.statistics
+# compare with earlier values
+
+# check the total artifact storage space separately
+builds_with_artifacts = p.builds.with_downloadable_artifacts.all
+
+artifact_storage = 0
+builds_with_artifacts.find_each do |build|
+ artifact_storage += build.artifacts_size
+end
+
+puts "#{artifact_storage} bytes"
```
### Identify deploy keys associated with blocked and non-member users
diff --git a/doc/api/broadcast_messages.md b/doc/api/broadcast_messages.md
index b22517db751..b98373b5a58 100644
--- a/doc/api/broadcast_messages.md
+++ b/doc/api/broadcast_messages.md
@@ -4,9 +4,7 @@ group: Activation
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
---
-# Broadcast Messages API
-
-> Introduced in GitLab 8.12.
+# Broadcast Messages API **(FREE SELF)**
Broadcast messages API operates on [broadcast messages](../user/admin_area/broadcast_messages.md).
diff --git a/doc/api/invitations.md b/doc/api/invitations.md
index 75ad9300668..36ff2d5bda4 100644
--- a/doc/api/invitations.md
+++ b/doc/api/invitations.md
@@ -4,7 +4,7 @@ group: Expansion
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
---
-# Invitations API
+# Invitations API **(FREE)**
Use the Invitations API to send email to users you want to join a group or project, and to list pending
invitations.
diff --git a/doc/ci/runners/README.md b/doc/ci/runners/README.md
index 8d21849c4d4..97513b1fa99 100644
--- a/doc/ci/runners/README.md
+++ b/doc/ci/runners/README.md
@@ -20,6 +20,9 @@ If you are using self-managed GitLab or you want to use your own runners on GitL
On GitLab.com, your jobs can run on [Linux](#linux-shared-runners) or [Windows](#windows-shared-runners-beta).
+The shared runners provided by GitLab are limited by [shared runner pipeline minutes quotas](../../user/admin_area/settings/continuous_integration.md#shared-runners-pipeline-minutes-quota)
+for each GitLab [subscription plan](../../subscriptions/gitlab_com/index.md#ci-pipeline-minutes).
+
### Linux shared runners
Linux shared runners on GitLab.com run in autoscale mode and are powered by Google Cloud Platform.
diff --git a/doc/ci/triggers/README.md b/doc/ci/triggers/README.md
index 4976756dff9..815a43bf3d2 100644
--- a/doc/ci/triggers/README.md
+++ b/doc/ci/triggers/README.md
@@ -262,7 +262,7 @@ of all types of variables.
Whether you craft a script or just run cURL directly, you can trigger jobs
in conjunction with cron. The example below triggers a job on the `main` branch
-branch of project with ID `9` every night at `00:30`:
+of project with ID `9` every night at `00:30`:
```shell
30 0 * * * curl --request POST --form token=TOKEN --form ref=main "https://gitlab.example.com/api/v4/projects/9/trigger/pipeline"
diff --git a/doc/development/testing_guide/best_practices.md b/doc/development/testing_guide/best_practices.md
index 4ed5bfc7eb5..c47502ed3a2 100644
--- a/doc/development/testing_guide/best_practices.md
+++ b/doc/development/testing_guide/best_practices.md
@@ -259,9 +259,9 @@ it 'sets the frobulance' do
end
it 'schedules a background job' do
- expect(BackgroundJob).to receive(:perform_async)
-
subject.execute
+
+ expect(BackgroundJob).to have_enqueued_sidekiq_job
end
```
@@ -271,11 +271,11 @@ combining the examples:
```ruby
it 'performs the expected side-effects' do
- expect(BackgroundJob).to receive(:perform_async)
-
expect { subject.execute }
.to change(Event, :count).by(1)
.and change { arg_0.frobulance }.to('wibble')
+
+ expect(BackgroundJob).to have_enqueued_sidekiq_job
end
```
@@ -738,6 +738,28 @@ The usage of `perform_enqueued_jobs` is useful only for testing delayed mail
deliveries, because our Sidekiq workers aren't inheriting from `ApplicationJob`
/ `ActiveJob::Base`.
+GitLab uses the [RSpec-Sidekiq](https://github.com/philostler/rspec-sidekiq) gem for expectations.
+We prefer you check that a job has been enqueued, rather than checking the worker has
+`received` the `perform_async` method:
+
+```ruby
+# bad
+expect(Worker).to receive(:perform_async).with(1, 'string')
+# Good
+expect(Worker).to have_enqueued_sidekiq_job(1, 'string')
+```
+
+The only exception to this rule: if the spec actually needs to make sure the job is
+enqueued only once, or a specific number of times:
+
+```ruby
+# good
+expect(Worker).to receive(:perform_async).with(1, 'string').once
+```
+
+If you need test that the job is only enqueued a specific number of times, you will have to disable the cop
+that enforces usage of `have_enqueued_sidekiq_job` (`RSpec/HaveEnqueuedSidekiqJob`) in that test.
+
#### DNS
DNS requests are stubbed universally in the test suite
diff --git a/doc/user/admin_area/settings/continuous_integration.md b/doc/user/admin_area/settings/continuous_integration.md
index 1bb772889a6..de6a425f810 100644
--- a/doc/user/admin_area/settings/continuous_integration.md
+++ b/doc/user/admin_area/settings/continuous_integration.md
@@ -122,7 +122,7 @@ shared runners per month. Setting this to `0` (default value) grants
unlimited pipeline minutes. While build limits are stored as minutes, the
counting is done in seconds. Usage resets on the first day of each month.
On GitLab.com, the quota is calculated based on your
-[subscription plan](https://about.gitlab.com/pricing/#gitlab-com).
+[subscription plan](../../../subscriptions/gitlab_com/index.md#ci-pipeline-minutes).
To change the pipelines minutes quota:
diff --git a/doc/user/group/index.md b/doc/user/group/index.md
index 706a221048c..cb6c3f44f7f 100644
--- a/doc/user/group/index.md
+++ b/doc/user/group/index.md
@@ -276,7 +276,7 @@ To share a given group, for example, `Frontend` with another group, for example,
1. From the left menu, select **Members**.
1. Select the **Invite group** tab.
1. In the **Select a group to invite** list, select `Engineering`.
-1. For the **Max access level**, select an access level.
+1. For the **Max role**, select a [role](../permissions.md).
1. Select **Invite**.
All the members of the `Engineering` group are added to the `Frontend` group.
@@ -298,7 +298,7 @@ To share a group after enabling this feature:
1. Go to your group's page.
1. In the left sidebar, go to **Members**, and then select **Invite a group**.
-1. Select a group, and select a **Max access level**.
+1. Select a group, and select a **Max role**.
1. (Optional) Select an **Access expiration date**.
1. Select **Invite**.
diff --git a/doc/user/project/integrations/webhooks.md b/doc/user/project/integrations/webhooks.md
index e049c19267b..33fe6150580 100644
--- a/doc/user/project/integrations/webhooks.md
+++ b/doc/user/project/integrations/webhooks.md
@@ -308,8 +308,10 @@ X-Gitlab-Event: Issue Hook
"duplicated_to_id": null,
"time_estimate": 0,
"total_time_spent": 0,
+ "time_change": 0,
"human_total_time_spent": null,
"human_time_estimate": null,
+ "human_time_change": null,
"weight": null,
"iid": 23,
"url": "http://example.com/diaspora/issues/23",
diff --git a/doc/user/project/members/share_project_with_groups.md b/doc/user/project/members/share_project_with_groups.md
index 085e4db0b94..caef5ef60b7 100644
--- a/doc/user/project/members/share_project_with_groups.md
+++ b/doc/user/project/members/share_project_with_groups.md
@@ -60,7 +60,7 @@ To share a project after enabling this feature:
1. Go to your project's page.
1. In the left sidebar, go to **Members**, and then select **Invite a group**.
-1. Select a group, and select a **Max access level**.
+1. Select a group, and select a **Max role**.
1. (Optional) Select an **Access expiration date**.
1. Select **Invite**.
diff --git a/lib/api/concerns/packages/conan_endpoints.rb b/lib/api/concerns/packages/conan_endpoints.rb
index eb762be8285..3194cdebde8 100644
--- a/lib/api/concerns/packages/conan_endpoints.rb
+++ b/lib/api/concerns/packages/conan_endpoints.rb
@@ -255,7 +255,7 @@ module API
delete do
authorize!(:destroy_package, project)
- track_package_event('delete_package', :conan, category: 'API::ConanPackages')
+ track_package_event('delete_package', :conan, category: 'API::ConanPackages', user: current_user, project: project, namespace: project.namespace)
package.destroy
end
diff --git a/lib/api/generic_packages.rb b/lib/api/generic_packages.rb
index d0680ad7bc5..a57d6bbcd2a 100644
--- a/lib/api/generic_packages.rb
+++ b/lib/api/generic_packages.rb
@@ -62,7 +62,7 @@ module API
authorize_upload!(project)
bad_request!('File is too large') if max_file_size_exceeded?
- ::Gitlab::Tracking.event(self.options[:for].name, 'push_package')
+ ::Gitlab::Tracking.event(self.options[:for].name, 'push_package', user: current_user, project: project, namespace: project.namespace)
create_package_file_params = declared_params.merge(build: current_authenticated_job)
::Packages::Generic::CreatePackageFileService
@@ -96,7 +96,7 @@ module API
package = ::Packages::Generic::PackageFinder.new(project).execute!(params[:package_name], params[:package_version])
package_file = ::Packages::PackageFileFinder.new(package, params[:file_name]).execute!
- ::Gitlab::Tracking.event(self.options[:for].name, 'pull_package')
+ ::Gitlab::Tracking.event(self.options[:for].name, 'pull_package', user: current_user, project: project, namespace: project.namespace)
present_carrierwave_file!(package_file.file)
end
diff --git a/lib/api/helpers/packages/conan/api_helpers.rb b/lib/api/helpers/packages/conan/api_helpers.rb
index b18f52b5be6..4b6dac39348 100644
--- a/lib/api/helpers/packages/conan/api_helpers.rb
+++ b/lib/api/helpers/packages/conan/api_helpers.rb
@@ -155,7 +155,7 @@ module API
conan_package_reference: params[:conan_package_reference]
).execute!
- track_package_event('pull_package', :conan, category: 'API::ConanPackages') if params[:file_name] == ::Packages::Conan::FileMetadatum::PACKAGE_BINARY
+ track_package_event('pull_package', :conan, category: 'API::ConanPackages', user: current_user, project: project, namespace: project.namespace) if params[:file_name] == ::Packages::Conan::FileMetadatum::PACKAGE_BINARY
present_carrierwave_file!(package_file.file)
end
@@ -170,7 +170,7 @@ module API
def track_push_package_event
if params[:file_name] == ::Packages::Conan::FileMetadatum::PACKAGE_BINARY && params[:file].size > 0 # rubocop: disable Style/ZeroLengthPredicate
- track_package_event('push_package', :conan, category: 'API::ConanPackages')
+ track_package_event('push_package', :conan, category: 'API::ConanPackages', user: current_user, project: project, namespace: project.namespace)
end
end
diff --git a/lib/api/project_snippets.rb b/lib/api/project_snippets.rb
index 899984fe0ba..084492fd503 100644
--- a/lib/api/project_snippets.rb
+++ b/lib/api/project_snippets.rb
@@ -75,7 +75,7 @@ module API
snippet_params = process_create_params(declared_params(include_missing: false))
- service_response = ::Snippets::CreateService.new(user_project, current_user, snippet_params).execute
+ service_response = ::Snippets::CreateService.new(project: user_project, current_user: current_user, params: snippet_params).execute
snippet = service_response.payload[:snippet]
if service_response.success?
@@ -116,7 +116,7 @@ module API
snippet_params = process_update_params(declared_params(include_missing: false))
- service_response = ::Snippets::UpdateService.new(user_project, current_user, snippet_params).execute(snippet)
+ service_response = ::Snippets::UpdateService.new(project: user_project, current_user: current_user, params: snippet_params).execute(snippet)
snippet = service_response.payload[:snippet]
if service_response.success?
diff --git a/lib/api/snippets.rb b/lib/api/snippets.rb
index 52b597fb788..b506192fe1c 100644
--- a/lib/api/snippets.rb
+++ b/lib/api/snippets.rb
@@ -84,7 +84,7 @@ module API
attrs = process_create_params(declared_params(include_missing: false))
- service_response = ::Snippets::CreateService.new(nil, current_user, attrs).execute
+ service_response = ::Snippets::CreateService.new(project: nil, current_user: current_user, params: attrs).execute
snippet = service_response.payload[:snippet]
if service_response.success?
@@ -126,7 +126,7 @@ module API
attrs = process_update_params(declared_params(include_missing: false))
- service_response = ::Snippets::UpdateService.new(nil, current_user, attrs).execute(snippet)
+ service_response = ::Snippets::UpdateService.new(project: nil, current_user: current_user, params: attrs).execute(snippet)
snippet = service_response.payload[:snippet]
diff --git a/lib/gitlab/experimentation/controller_concern.rb b/lib/gitlab/experimentation/controller_concern.rb
index e53689eb89b..ca9205a8f8c 100644
--- a/lib/gitlab/experimentation/controller_concern.rb
+++ b/lib/gitlab/experimentation/controller_concern.rb
@@ -56,7 +56,7 @@ module Gitlab
return if dnt_enabled?
track_experiment_event_for(experiment_key, action, value, subject: subject) do |tracking_data|
- ::Gitlab::Tracking.event(tracking_data.delete(:category), tracking_data.delete(:action), **tracking_data)
+ ::Gitlab::Tracking.event(tracking_data.delete(:category), tracking_data.delete(:action), **tracking_data.merge!(user: current_user))
end
end
diff --git a/lib/gitlab/hook_data/issue_builder.rb b/lib/gitlab/hook_data/issue_builder.rb
index d5595e80bdf..2d1bb515058 100644
--- a/lib/gitlab/hook_data/issue_builder.rb
+++ b/lib/gitlab/hook_data/issue_builder.rb
@@ -7,6 +7,7 @@ module Gitlab
assignees
labels
total_time_spent
+ time_change
].freeze
def self.safe_hook_attributes
@@ -43,7 +44,9 @@ module Gitlab
description: absolute_image_urls(issue.description),
url: Gitlab::UrlBuilder.build(issue),
total_time_spent: issue.total_time_spent,
+ time_change: issue.time_change,
human_total_time_spent: issue.human_total_time_spent,
+ human_time_change: issue.human_time_change,
human_time_estimate: issue.human_time_estimate,
assignee_ids: issue.assignee_ids,
assignee_id: issue.assignee_ids.first, # This key is deprecated
diff --git a/lib/gitlab/hook_data/merge_request_builder.rb b/lib/gitlab/hook_data/merge_request_builder.rb
index ae2ec424ce5..db807a3c557 100644
--- a/lib/gitlab/hook_data/merge_request_builder.rb
+++ b/lib/gitlab/hook_data/merge_request_builder.rb
@@ -37,6 +37,7 @@ module Gitlab
assignees
labels
total_time_spent
+ time_change
].freeze
alias_method :merge_request, :object
@@ -50,7 +51,9 @@ module Gitlab
last_commit: merge_request.diff_head_commit&.hook_attrs,
work_in_progress: merge_request.work_in_progress?,
total_time_spent: merge_request.total_time_spent,
+ time_change: merge_request.time_change,
human_total_time_spent: merge_request.human_total_time_spent,
+ human_time_change: merge_request.human_time_change,
human_time_estimate: merge_request.human_time_estimate,
assignee_ids: merge_request.assignee_ids,
assignee_id: merge_request.assignee_ids.first, # This key is deprecated
diff --git a/lib/gitlab/time_tracking_formatter.rb b/lib/gitlab/time_tracking_formatter.rb
index bfdfb01093f..67ecf498cf7 100644
--- a/lib/gitlab/time_tracking_formatter.rb
+++ b/lib/gitlab/time_tracking_formatter.rb
@@ -24,6 +24,12 @@ module Gitlab
end
def output(seconds)
+ seconds.to_i < 0 ? negative_output(seconds) : positive_output(seconds)
+ end
+
+ private
+
+ def positive_output(seconds)
ChronicDuration.output(
seconds,
CUSTOM_DAY_AND_MONTH_LENGTH.merge(
@@ -34,7 +40,9 @@ module Gitlab
nil
end
- private
+ def negative_output(seconds)
+ "-" + positive_output(seconds.abs)
+ end
def limit_to_hours_setting
Gitlab::CurrentSettings.time_tracking_limit_to_hours
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 1cdedf752fc..5d197a876bd 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -654,10 +654,10 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
+msgid "%{link_start}Learn more%{link_end} about roles."
msgstr ""
-msgid "%{link_start}Read more%{link_end} about role permissions"
+msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
@@ -6043,15 +6043,15 @@ msgstr ""
msgid "Change path"
msgstr ""
-msgid "Change permissions"
-msgstr ""
-
msgid "Change reviewer(s)"
msgstr ""
msgid "Change reviewer(s)."
msgstr ""
+msgid "Change role"
+msgstr ""
+
msgid "Change status"
msgstr ""
@@ -6430,9 +6430,6 @@ msgstr ""
msgid "Choose a group"
msgstr ""
-msgid "Choose a role permission"
-msgstr ""
-
msgid "Choose a template"
msgstr ""
@@ -17938,7 +17935,7 @@ msgstr ""
msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
msgstr ""
-msgid "InviteMembersModal|%{linkStart}Read more%{linkEnd} about role permissions"
+msgid "InviteMembersModal|%{linkStart}Learn more%{linkEnd} about roles."
msgstr ""
msgid "InviteMembersModal|Access expiration date (optional)"
@@ -17947,9 +17944,6 @@ msgstr ""
msgid "InviteMembersModal|Cancel"
msgstr ""
-msgid "InviteMembersModal|Choose a role permission"
-msgstr ""
-
msgid "InviteMembersModal|Close invite team members"
msgstr ""
@@ -17974,6 +17968,9 @@ msgstr ""
msgid "InviteMembersModal|Select a group to invite"
msgstr ""
+msgid "InviteMembersModal|Select a role"
+msgstr ""
+
msgid "InviteMembersModal|Select members or type email addresses"
msgstr ""
@@ -20138,9 +20135,6 @@ msgstr ""
msgid "Max Project Import requests per minute per user"
msgstr ""
-msgid "Max access level"
-msgstr ""
-
msgid "Max authenticated API requests per period per user"
msgstr ""
@@ -29210,6 +29204,9 @@ msgstr ""
msgid "Select a repository"
msgstr ""
+msgid "Select a role"
+msgstr ""
+
msgid "Select a shared template repository for all projects on this instance."
msgstr ""
diff --git a/package.json b/package.json
index e251ac6122d..d81030cb666 100644
--- a/package.json
+++ b/package.json
@@ -114,7 +114,6 @@
"dateformat": "^4.5.1",
"deckar01-task_list": "^2.3.1",
"diff": "^3.4.0",
- "document-register-element": "1.14.3",
"dompurify": "^2.2.9",
"dropzone": "^4.2.0",
"editorconfig": "^0.15.3",
diff --git a/rubocop/cop/rspec/have_enqueued_sidekiq_job.rb b/rubocop/cop/rspec/have_enqueued_sidekiq_job.rb
new file mode 100644
index 00000000000..4b0beb10723
--- /dev/null
+++ b/rubocop/cop/rspec/have_enqueued_sidekiq_job.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+module RuboCop
+ module Cop
+ module RSpec
+ # This cop checks for `expect(worker).to receive(:perform_async)` usage in specs
+ #
+ # @example
+ # # bad
+ # it "enqueues a worker" do
+ # expect(MyWorker).to receive(:perform_async)
+ # end
+ #
+ # # good
+ # it "enqueues a worker" do
+ # expect(MyWorker).to have_enqueued_sidekiq_job
+ # end
+ #
+ # # bad
+ # it "enqueues a worker" do
+ # expect(MyWorker).to receive(:perform_async).with(1, 2)
+ # end
+ #
+ # # good
+ # it "enqueues a worker" do
+ # expect(MyWorker).to have_enqueued_sidekiq_job(1, 2)
+ # end
+ #
+ class HaveEnqueuedSidekiqJob < RuboCop::Cop::Cop
+ MESSAGE = 'Do not use `receive(:perform_async)` to check a job has been enqueued, use `have_enqueued_sidekiq_job` instead.'
+
+ def_node_search :expect_to_receive_perform_async?, <<~PATTERN
+ (send
+ (send nil? :expect ...)
+ {:to :not_to :to_not}
+ {
+ (send nil? :receive (sym :perform_async))
+
+ (send
+ (send nil? :receive (sym :perform_async)) ...
+ )
+
+ (send
+ (send
+ (send nil? :receive (sym :perform_async)) ...
+ ) ...
+ )
+ }
+ )
+ PATTERN
+
+ def on_send(node)
+ return unless expect_to_receive_perform_async?(node)
+
+ add_offense(node, location: :expression, message: MESSAGE)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/frontend/members/components/table/role_dropdown_spec.js b/spec/frontend/members/components/table/role_dropdown_spec.js
index c8b6bead450..a4a4c620921 100644
--- a/spec/frontend/members/components/table/role_dropdown_spec.js
+++ b/spec/frontend/members/components/table/role_dropdown_spec.js
@@ -88,7 +88,7 @@ describe('RoleDropdown', () => {
});
it('renders dropdown header', () => {
- expect(getByTextInDropdownMenu('Change permissions').exists()).toBe(true);
+ expect(getByTextInDropdownMenu('Change role').exists()).toBe(true);
});
it('sets dropdown toggle and checks selected role', () => {
diff --git a/spec/lib/gitlab/ci/config/entry/job_spec.rb b/spec/lib/gitlab/ci/config/entry/job_spec.rb
index 1d23ab0c2c7..69b6d1666ff 100644
--- a/spec/lib/gitlab/ci/config/entry/job_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/job_spec.rb
@@ -658,7 +658,7 @@ RSpec.describe Gitlab::Ci::Config::Entry::Job do
let(:config) { { script: 'deploy', when: 'delayed' } }
it 'is a delayed' do
- expect(entry).to be_delayed
+ expect(entry.delayed?).to be_truthy
end
end
@@ -666,7 +666,7 @@ RSpec.describe Gitlab::Ci::Config::Entry::Job do
let(:config) { { script: 'deploy' } }
it 'is not a delayed' do
- expect(entry).not_to be_delayed
+ expect(entry.delayed?).to be_falsey
end
end
end
diff --git a/spec/lib/gitlab/database/postgres_index_spec.rb b/spec/lib/gitlab/database/postgres_index_spec.rb
index 2fda9b85c5a..47e94230ba1 100644
--- a/spec/lib/gitlab/database/postgres_index_spec.rb
+++ b/spec/lib/gitlab/database/postgres_index_spec.rb
@@ -69,15 +69,15 @@ RSpec.describe Gitlab::Database::PostgresIndex do
describe '#unique?' do
it 'returns true for a unique index' do
- expect(find('public.bar_key')).to be_unique
+ expect(find('public.bar_key').unique?).to be_truthy
end
it 'returns false for a regular, non-unique index' do
- expect(find('public.foo_idx')).not_to be_unique
+ expect(find('public.foo_idx').unique?).to be_falsey
end
it 'returns true for a primary key index' do
- expect(find('public.example_table_pkey')).to be_unique
+ expect(find('public.example_table_pkey').unique?).to be_truthy
end
end
diff --git a/spec/lib/gitlab/experimentation/controller_concern_spec.rb b/spec/lib/gitlab/experimentation/controller_concern_spec.rb
index 5419a01ea3e..7a619c9f155 100644
--- a/spec/lib/gitlab/experimentation/controller_concern_spec.rb
+++ b/spec/lib/gitlab/experimentation/controller_concern_spec.rb
@@ -196,9 +196,12 @@ RSpec.describe Gitlab::Experimentation::ControllerConcern, type: :controller do
end
describe '#track_experiment_event', :snowplow do
+ let(:user) { build(:user) }
+
context 'when the experiment is enabled' do
before do
stub_experiment(test_experiment: true)
+ allow(controller).to receive(:current_user).and_return(user)
end
context 'the user is part of the experimental group' do
@@ -213,7 +216,8 @@ RSpec.describe Gitlab::Experimentation::ControllerConcern, type: :controller do
category: 'Team',
action: 'start',
property: 'experimental_group',
- value: 1
+ value: 1,
+ user: user
)
end
end
@@ -230,7 +234,8 @@ RSpec.describe Gitlab::Experimentation::ControllerConcern, type: :controller do
category: 'Team',
action: 'start',
property: 'control_group',
- value: 1
+ value: 1,
+ user: user
)
end
end
@@ -247,7 +252,8 @@ RSpec.describe Gitlab::Experimentation::ControllerConcern, type: :controller do
category: 'Team',
action: 'start',
property: 'control_group',
- value: 1
+ value: 1,
+ user: user
)
end
end
@@ -280,7 +286,8 @@ RSpec.describe Gitlab::Experimentation::ControllerConcern, type: :controller do
action: 'start',
property: 'control_group',
value: 1,
- label: Digest::MD5.hexdigest('abc')
+ label: Digest::MD5.hexdigest('abc'),
+ user: user
)
end
@@ -294,7 +301,8 @@ RSpec.describe Gitlab::Experimentation::ControllerConcern, type: :controller do
action: 'start',
property: 'control_group',
value: 1,
- label: Digest::MD5.hexdigest('somestring')
+ label: Digest::MD5.hexdigest('somestring'),
+ user: user
)
end
end
@@ -313,7 +321,8 @@ RSpec.describe Gitlab::Experimentation::ControllerConcern, type: :controller do
action: 'start',
property: 'control_group',
value: 1,
- label: cookies.permanent.signed[:experimentation_subject_id]
+ label: cookies.permanent.signed[:experimentation_subject_id],
+ user: user
)
end
end
diff --git a/spec/lib/gitlab/hook_data/issue_builder_spec.rb b/spec/lib/gitlab/hook_data/issue_builder_spec.rb
index 8f898d898de..8f976bcf09d 100644
--- a/spec/lib/gitlab/hook_data/issue_builder_spec.rb
+++ b/spec/lib/gitlab/hook_data/issue_builder_spec.rb
@@ -42,8 +42,10 @@ RSpec.describe Gitlab::HookData::IssueBuilder do
it 'includes additional attrs' do
expect(data).to include(:total_time_spent)
+ expect(data).to include(:time_change)
expect(data).to include(:human_time_estimate)
expect(data).to include(:human_total_time_spent)
+ expect(data).to include(:human_time_change)
expect(data).to include(:assignee_ids)
expect(data).to include(:state)
expect(data).to include('labels' => [label.hook_attrs])
diff --git a/spec/lib/gitlab/hook_data/merge_request_builder_spec.rb b/spec/lib/gitlab/hook_data/merge_request_builder_spec.rb
index 0339faa9fcf..9e6ad35861f 100644
--- a/spec/lib/gitlab/hook_data/merge_request_builder_spec.rb
+++ b/spec/lib/gitlab/hook_data/merge_request_builder_spec.rb
@@ -57,8 +57,10 @@ RSpec.describe Gitlab::HookData::MergeRequestBuilder do
expect(data).to include(:last_commit)
expect(data).to include(:work_in_progress)
expect(data).to include(:total_time_spent)
+ expect(data).to include(:time_change)
expect(data).to include(:human_time_estimate)
expect(data).to include(:human_total_time_spent)
+ expect(data).to include(:human_time_change)
end
context 'when the MR has an image in the description' do
diff --git a/spec/lib/gitlab/time_tracking_formatter_spec.rb b/spec/lib/gitlab/time_tracking_formatter_spec.rb
index 8bbd1263057..ab0611e6b6a 100644
--- a/spec/lib/gitlab/time_tracking_formatter_spec.rb
+++ b/spec/lib/gitlab/time_tracking_formatter_spec.rb
@@ -47,5 +47,11 @@ RSpec.describe Gitlab::TimeTrackingFormatter do
it { expect(subject).to eq('1w 1d 1h 40m') }
end
+
+ context 'handles negative time input' do
+ let(:num_seconds) { -178_800 }
+
+ it { expect(subject).to eq('-1w 1d 1h 40m') }
+ end
end
end
diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb
index ed8487cac88..c8430d669b8 100644
--- a/spec/models/ci/build_spec.rb
+++ b/spec/models/ci/build_spec.rb
@@ -1842,7 +1842,7 @@ RSpec.describe Ci::Build do
end
describe '#retryable?' do
- subject { build }
+ subject { build.retryable? }
context 'when build is retryable' do
context 'when build is successful' do
@@ -1850,7 +1850,7 @@ RSpec.describe Ci::Build do
build.success!
end
- it { is_expected.to be_retryable }
+ it { is_expected.to be_truthy }
end
context 'when build is failed' do
@@ -1858,7 +1858,7 @@ RSpec.describe Ci::Build do
build.drop!
end
- it { is_expected.to be_retryable }
+ it { is_expected.to be_truthy }
end
context 'when build is canceled' do
@@ -1866,7 +1866,7 @@ RSpec.describe Ci::Build do
build.cancel!
end
- it { is_expected.to be_retryable }
+ it { is_expected.to be_truthy }
end
end
@@ -1876,7 +1876,7 @@ RSpec.describe Ci::Build do
build.run!
end
- it { is_expected.not_to be_retryable }
+ it { is_expected.to be_falsey }
end
context 'when build is skipped' do
@@ -1884,7 +1884,7 @@ RSpec.describe Ci::Build do
build.skip!
end
- it { is_expected.not_to be_retryable }
+ it { is_expected.to be_falsey }
end
context 'when build is degenerated' do
@@ -1892,7 +1892,7 @@ RSpec.describe Ci::Build do
build.degenerate!
end
- it { is_expected.not_to be_retryable }
+ it { is_expected.to be_falsey }
end
context 'when a canceled build has been retried already' do
@@ -1903,7 +1903,7 @@ RSpec.describe Ci::Build do
end
context 'when prevent_retry_of_retried_jobs feature flag is enabled' do
- it { is_expected.not_to be_retryable }
+ it { is_expected.to be_falsey }
end
context 'when prevent_retry_of_retried_jobs feature flag is disabled' do
@@ -1911,7 +1911,7 @@ RSpec.describe Ci::Build do
stub_feature_flags(prevent_retry_of_retried_jobs: false)
end
- it { is_expected.to be_retryable }
+ it { is_expected.to be_truthy }
end
end
end
diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb
index 14db9b530db..b3dc486081c 100644
--- a/spec/models/concerns/issuable_spec.rb
+++ b/spec/models/concerns/issuable_spec.rb
@@ -715,6 +715,12 @@ RSpec.describe Issuable do
expect(issue.total_time_spent).to eq(1800)
end
+ it 'stores the time change' do
+ spend_time(1800)
+
+ expect(issue.time_change).to eq(1800)
+ end
+
it 'updates issues updated_at' do
issue
@@ -735,6 +741,12 @@ RSpec.describe Issuable do
expect(issue.total_time_spent).to eq(900)
end
+ it 'stores negative time change' do
+ spend_time(-900)
+
+ expect(issue.time_change).to eq(-900)
+ end
+
context 'when time to subtract exceeds the total time spent' do
it 'raise a validation error' do
Timecop.travel(1.minute.from_now) do
@@ -829,7 +841,7 @@ RSpec.describe Issuable do
it_behaves_like 'matches_cross_reference_regex? fails fast'
end
- context "note with long path string" do
+ context "note with long path string", quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/35269' do
let(:project) { create(:project, :public, :repository) }
let(:mentionable) { project.commit }
diff --git a/spec/requests/api/conan_instance_packages_spec.rb b/spec/requests/api/conan_instance_packages_spec.rb
index 817530f0bad..ff3b332c620 100644
--- a/spec/requests/api/conan_instance_packages_spec.rb
+++ b/spec/requests/api/conan_instance_packages_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe API::ConanInstancePackages do
+ let(:snowplow_standard_context_params) { { user: user, project: project, namespace: project.namespace } }
+
include_context 'conan api setup'
describe 'GET /api/v4/packages/conan/v1/ping' do
diff --git a/spec/requests/api/generic_packages_spec.rb b/spec/requests/api/generic_packages_spec.rb
index 6886fff2282..378ee2f3e7c 100644
--- a/spec/requests/api/generic_packages_spec.rb
+++ b/spec/requests/api/generic_packages_spec.rb
@@ -19,6 +19,7 @@ RSpec.describe API::GenericPackages do
let(:user) { personal_access_token.user }
let(:ci_build) { create(:ci_build, :running, user: user, project: project) }
+ let(:snowplow_standard_context_params) { { user: user, project: project, namespace: project.namespace } }
def auth_header
return {} if user_role == :anonymous
diff --git a/spec/requests/api/graphql/mutations/snippets/create_spec.rb b/spec/requests/api/graphql/mutations/snippets/create_spec.rb
index d944c9e9e57..214c804c519 100644
--- a/spec/requests/api/graphql/mutations/snippets/create_spec.rb
+++ b/spec/requests/api/graphql/mutations/snippets/create_spec.rb
@@ -86,7 +86,7 @@ RSpec.describe 'Creating a Snippet' do
it 'passes disable_spam_action_service param to service' do
expect(::Snippets::CreateService)
.to receive(:new)
- .with(anything, anything, hash_including(disable_spam_action_service: true))
+ .with(project: anything, current_user: anything, params: hash_including(disable_spam_action_service: true))
.and_call_original
subject
@@ -190,7 +190,7 @@ RSpec.describe 'Creating a Snippet' do
it do
expect(::Snippets::CreateService).to receive(:new)
- .with(nil, user, hash_including(files: expected_value))
+ .with(project: nil, current_user: user, params: hash_including(files: expected_value))
.and_return(double(execute: creation_response))
subject
diff --git a/spec/requests/api/graphql/mutations/snippets/update_spec.rb b/spec/requests/api/graphql/mutations/snippets/update_spec.rb
index 28ab593526a..77efb786dcb 100644
--- a/spec/requests/api/graphql/mutations/snippets/update_spec.rb
+++ b/spec/requests/api/graphql/mutations/snippets/update_spec.rb
@@ -90,7 +90,7 @@ RSpec.describe 'Updating a Snippet' do
it 'passes disable_spam_action_service param to service' do
expect(::Snippets::UpdateService)
.to receive(:new)
- .with(anything, anything, hash_including(disable_spam_action_service: true))
+ .with(project: anything, current_user: anything, params: hash_including(disable_spam_action_service: true))
.and_call_original
subject
diff --git a/spec/rubocop/cop/rspec/have_enqueued_sidekiq_job_spec.rb b/spec/rubocop/cop/rspec/have_enqueued_sidekiq_job_spec.rb
new file mode 100644
index 00000000000..506cdb6e4e8
--- /dev/null
+++ b/spec/rubocop/cop/rspec/have_enqueued_sidekiq_job_spec.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require_relative '../../../../rubocop/cop/rspec/have_enqueued_sidekiq_job'
+
+RSpec.describe RuboCop::Cop::RSpec::HaveEnqueuedSidekiqJob do
+ let(:source_file) { 'spec/foo_spec.rb' }
+
+ subject(:cop) { described_class.new }
+
+ shared_examples 'cop' do |good:, bad:|
+ context "using #{bad} call" do
+ it 'registers an offense', :aggregate_failures do
+ expect_offense(<<~CODE, node: bad)
+ %{node}
+ ^{node} Do not use `receive(:perform_async)` to check a job has been enqueued, use `have_enqueued_sidekiq_job` instead.
+ CODE
+ end
+ end
+
+ context "using #{good} call" do
+ it 'does not register an offense' do
+ expect_no_offenses(good)
+ end
+ end
+ end
+
+ it_behaves_like 'cop',
+ bad: 'expect(Worker).to receive(:perform_async)',
+ good: 'expect(Worker).to have_enqueued_sidekiq_job'
+
+ include_examples 'cop',
+ bad: 'expect(Worker).not_to receive(:perform_async)',
+ good: 'expect(Worker).not_to have_enqueued_sidekiq_job'
+
+ include_examples 'cop',
+ bad: 'expect(Worker).to_not receive(:perform_async)',
+ good: 'expect(Worker).to_not have_enqueued_sidekiq_job'
+
+ include_examples 'cop',
+ bad: 'expect(Worker).to receive(:perform_async).with(1)',
+ good: 'expect(Worker).to have_enqueued_sidekiq_job(1)'
+
+ include_examples 'cop',
+ bad: 'expect(Worker).to receive(:perform_async).with(1).once',
+ good: 'expect(Worker).to have_enqueued_sidekiq_job(1)'
+
+ include_examples 'cop',
+ bad: 'expect(any_variable_or_method).to receive(:perform_async).with(1)',
+ good: 'expect(any_variable_or_method).to have_enqueued_sidekiq_job(1)'
+end
diff --git a/spec/services/ci/update_build_state_service_spec.rb b/spec/services/ci/update_build_state_service_spec.rb
index b0405226275..5bb3843da8f 100644
--- a/spec/services/ci/update_build_state_service_spec.rb
+++ b/spec/services/ci/update_build_state_service_spec.rb
@@ -15,6 +15,24 @@ RSpec.describe Ci::UpdateBuildStateService do
stub_feature_flags(ci_enable_live_trace: true)
end
+ context 'when build has unknown failure reason' do
+ let(:params) do
+ {
+ output: { checksum: 'crc32:12345678', bytesize: 123 },
+ state: 'failed',
+ failure_reason: 'no idea here',
+ exit_code: 42
+ }
+ end
+
+ it 'updates a build status' do
+ result = subject.execute
+
+ expect(build).to be_failed
+ expect(result.status).to eq 200
+ end
+ end
+
context 'when build does not have checksum' do
context 'when state has changed' do
let(:params) { { state: 'success' } }
diff --git a/spec/services/merge_requests/update_service_spec.rb b/spec/services/merge_requests/update_service_spec.rb
index b62009e6cdc..6ec2b158d30 100644
--- a/spec/services/merge_requests/update_service_spec.rb
+++ b/spec/services/merge_requests/update_service_spec.rb
@@ -297,6 +297,7 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
reviewers: [],
milestone: nil,
total_time_spent: 0,
+ time_change: 0,
description: "FYI #{user2.to_reference}"
}
)
diff --git a/spec/services/snippets/create_service_spec.rb b/spec/services/snippets/create_service_spec.rb
index 32a09e1afc8..eb6e85eb408 100644
--- a/spec/services/snippets/create_service_spec.rb
+++ b/spec/services/snippets/create_service_spec.rb
@@ -20,7 +20,7 @@ RSpec.describe Snippets::CreateService do
let(:extra_opts) { {} }
let(:creator) { admin }
- subject { described_class.new(project, creator, opts).execute }
+ subject { described_class.new(project: project, current_user: creator, params: opts).execute }
let(:snippet) { subject.payload[:snippet] }
diff --git a/spec/services/snippets/update_service_spec.rb b/spec/services/snippets/update_service_spec.rb
index e737c00ae67..46bc62e11ef 100644
--- a/spec/services/snippets/update_service_spec.rb
+++ b/spec/services/snippets/update_service_spec.rb
@@ -20,7 +20,7 @@ RSpec.describe Snippets::UpdateService do
let(:extra_opts) { {} }
let(:options) { base_opts.merge(extra_opts) }
let(:updater) { user }
- let(:service) { Snippets::UpdateService.new(project, updater, options) }
+ let(:service) { Snippets::UpdateService.new(project: project, current_user: updater, params: options) }
subject { service.execute(snippet) }
diff --git a/spec/support/shared_examples/graphql/mutations/can_mutate_spammable_examples.rb b/spec/support/shared_examples/graphql/mutations/can_mutate_spammable_examples.rb
index fc795012ce7..5e15c91cd41 100644
--- a/spec/support/shared_examples/graphql/mutations/can_mutate_spammable_examples.rb
+++ b/spec/support/shared_examples/graphql/mutations/can_mutate_spammable_examples.rb
@@ -6,9 +6,9 @@ RSpec.shared_examples 'a mutation which can mutate a spammable' do
describe "#additional_spam_params" do
it 'passes additional spam params to the service' do
args = [
- anything,
- anything,
- hash_including(
+ project: anything,
+ current_user: anything,
+ params: hash_including(
api: true,
request: instance_of(ActionDispatch::Request),
captcha_response: captcha_response,
diff --git a/spec/support/shared_examples/requests/api/tracking_shared_examples.rb b/spec/support/shared_examples/requests/api/tracking_shared_examples.rb
index 826139635ed..af13e3fc14d 100644
--- a/spec/support/shared_examples/requests/api/tracking_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/tracking_shared_examples.rb
@@ -4,6 +4,6 @@ RSpec.shared_examples 'a gitlab tracking event' do |category, action|
it "creates a gitlab tracking event #{action}", :snowplow do
subject
- expect_snowplow_event(category: category, action: action)
+ expect_snowplow_event(category: category, action: action, **snowplow_standard_context_params)
end
end
diff --git a/spec/workers/pipeline_hooks_worker_spec.rb b/spec/workers/pipeline_hooks_worker_spec.rb
index 7c75cdc8823..5957b355c8e 100644
--- a/spec/workers/pipeline_hooks_worker_spec.rb
+++ b/spec/workers/pipeline_hooks_worker_spec.rb
@@ -22,4 +22,9 @@ RSpec.describe PipelineHooksWorker do
end
end
end
+
+ it_behaves_like 'worker with data consistency',
+ described_class,
+ feature_flag: :load_balancing_for_pipeline_hooks_worker,
+ data_consistency: :delayed
end
diff --git a/yarn.lock b/yarn.lock
index f9a1e6161f8..e5b5c8cc88b 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4438,13 +4438,6 @@ doctrine@^3.0.0:
dependencies:
esutils "^2.0.2"
-document-register-element@1.14.3:
- version "1.14.3"
- resolved "https://registry.yarnpkg.com/document-register-element/-/document-register-element-1.14.3.tgz#3335d4578df6a1536a34595b91cca36dd5db61d7"
- integrity sha512-SbJTzoQXLTcYxnpdDNRZXu/gwsGSShemXpvj6Pa6ujRwJFpJ41siil4tk4y+cQXnqylS6mc2Rtxp/PkMzfkqyQ==
- dependencies:
- lightercollective "^0.3.0"
-
dom-accessibility-api@^0.5.1:
version "0.5.3"
resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.3.tgz#0ea493c924d4070dfbf531c4aaca3d7a2c601aab"
@@ -7740,11 +7733,6 @@ lie@~3.1.0:
dependencies:
immediate "~3.0.5"
-lightercollective@^0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/lightercollective/-/lightercollective-0.3.0.tgz#1f07638642ec645d70bdb69ab2777676f35a28f0"
- integrity sha512-RFOLSUVvwdK3xA0P8o6G7QGXLIyy1L2qv5caEI7zXN5ciaEjbAriRF182kbsoJ1S1TgvpyGcN485fMky6qxOPw==
-
lines-and-columns@^1.1.6:
version "1.1.6"
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00"