diff options
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 @@ -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" |