summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab/CODEOWNERS629
-rw-r--r--.rubocop_todo/rails/save_bang.yml9
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--app/assets/javascripts/badges/components/badge_list_row.vue5
-rw-r--r--app/assets/javascripts/environments/components/deployment.vue8
-rw-r--r--app/assets/javascripts/google_cloud/components/service_accounts_form.vue12
-rw-r--r--app/assets/javascripts/issues/list/components/issues_list_app.vue1
-rw-r--r--app/assets/javascripts/lib/utils/constants.js1
-rw-r--r--app/assets/javascripts/lib/utils/number_utils.js23
-rw-r--r--app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue7
-rw-r--r--app/assets/javascripts/sidebar/components/todo_toggle/sidebar_todo_widget.vue11
-rw-r--r--app/assets/javascripts/vue_shared/issuable/list/components/issuable_list_root.vue6
-rw-r--r--app/assets/javascripts/vue_shared/issuable/list/components/issuable_tabs.vue8
-rw-r--r--app/finders/issues_finder.rb6
-rw-r--r--app/finders/issues_finder/params.rb12
-rw-r--r--app/graphql/types/ci/runner_type.rb39
-rw-r--r--app/models/ci/pipeline.rb6
-rw-r--r--app/models/container_repository.rb9
-rw-r--r--app/models/issue.rb6
-rw-r--r--app/services/auth/container_registry_authentication_service.rb25
-rw-r--r--app/services/ci/retry_build_service.rb27
-rw-r--r--app/uploaders/import_export_uploader.rb4
-rw-r--r--app/views/profiles/accounts/_providers.html.haml2
-rw-r--r--app/workers/concerns/application_worker.rb19
-rw-r--r--config/feature_flags/development/create_deployment_in_separate_transaction.yml8
-rw-r--r--config/feature_flags/development/skip_scheduling_workers_for_replicas.yml8
-rw-r--r--data/removals/14_6/limit_trigger_pipelines.yml6
-rw-r--r--data/removals/14_6/removal-release-cli-s3.yml6
-rw-r--r--doc/administration/postgresql/database_load_balancing.md4
-rw-r--r--doc/api/graphql/reference/index.md1
-rw-r--r--doc/api/issues.md12
-rw-r--r--doc/ci/yaml/script.md2
-rw-r--r--doc/development/database/dbcheck-migrations-job.md67
-rw-r--r--doc/development/database/index.md1
-rw-r--r--doc/development/database_review.md2
-rw-r--r--doc/subscriptions/bronze_starter.md4
-rw-r--r--doc/update/removals.md10
-rw-r--r--doc/user/application_security/policies/img/scan_result_policy_yaml_mode_v14_6.pngbin0 -> 76484 bytes
-rw-r--r--doc/user/application_security/policies/index.md200
-rw-r--r--doc/user/profile/account/delete_account.md15
-rw-r--r--doc/user/project/clusters/kubernetes_pod_logs.md4
-rw-r--r--doc/user/project/issue_board.md6
-rw-r--r--doc/user/project/issues/csv_export.md46
-rw-r--r--doc/user/project/issues/design_management.md26
-rw-r--r--doc/user/project/merge_requests/test_coverage_visualization.md71
-rw-r--r--doc/user/project/milestones/burndown_and_burnup_charts.md4
-rw-r--r--doc/user/project/milestones/img/milestones_new_group_milestone_v13_5.pngbin47296 -> 0 bytes
-rw-r--r--doc/user/project/milestones/index.md31
-rw-r--r--lib/api/issues.rb2
-rw-r--r--lib/bitbucket_server/representation/repo.rb2
-rw-r--r--lib/gitlab/ci/pipeline/chain/build.rb4
-rw-r--r--lib/gitlab/ci/pipeline/chain/create_deployments.rb2
-rw-r--r--lib/gitlab/ci/pipeline/chain/ensure_environments.rb2
-rw-r--r--lib/gitlab/ci/pipeline/chain/ensure_resource_groups.rb2
-rw-r--r--lib/gitlab/ci/pipeline/seed/build.rb35
-rw-r--r--locale/gitlab.pot9
-rw-r--r--spec/features/issues/user_sorts_issues_spec.rb2
-rw-r--r--spec/finders/issues_finder_spec.rb30
-rw-r--r--spec/frontend/environments/deployment_spec.js23
-rw-r--r--spec/frontend/google_cloud/components/service_accounts_form_spec.js19
-rw-r--r--spec/frontend/lib/utils/number_utility_spec.js16
-rw-r--r--spec/frontend/sidebar/components/todo_toggle/sidebar_todo_widget_spec.js6
-rw-r--r--spec/frontend/vue_shared/issuable/list/components/issuable_tabs_spec.js86
-rw-r--r--spec/frontend/vue_shared/issuable/list/mock_data.js2
-rw-r--r--spec/graphql/types/ci/runner_type_spec.rb2
-rw-r--r--spec/lib/bitbucket_server/representation/repo_spec.rb5
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/create_deployments_spec.rb12
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/ensure_environments_spec.rb12
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/ensure_resource_groups_spec.rb12
-rw-r--r--spec/lib/gitlab/ci/pipeline/seed/build_spec.rb165
-rw-r--r--spec/models/container_repository_spec.rb64
-rw-r--r--spec/requests/api/graphql/ci/runner_spec.rb51
-rw-r--r--spec/requests/api/issues/issues_spec.rb28
-rw-r--r--spec/services/ci/retry_build_service_spec.rb17
-rw-r--r--spec/support/shared_examples/services/container_registry_auth_service_shared_examples.rb86
-rw-r--r--spec/uploaders/import_export_uploader_spec.rb28
-rw-r--r--spec/workers/concerns/application_worker_spec.rb39
77 files changed, 1521 insertions, 653 deletions
diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS
index 71e4571b603..f31b6a12c4c 100644
--- a/.gitlab/CODEOWNERS
+++ b/.gitlab/CODEOWNERS
@@ -208,152 +208,589 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/.markdownlint @marcel.amirault @eread @aqualls @cnorris
/doc/ @gl-docsteam
/doc/.vale/ @marcel.amirault @eread @aqualls @cnorris
+/doc/administration/application_settings_cache.md @marcia
+/doc/administration/audit_event_streaming.md @eread
+/doc/administration/audit_events.md @eread
+/doc/administration/audit_reports.md @eread
+/doc/administration/auditor_users.md @axil
+/doc/administration/auth/atlassian.md @eread
+/doc/administration/auth/authentiq.md @eread
+/doc/administration/auth/cognito.md @eread
+/doc/administration/auth/crowd.md @eread
+/doc/administration/auth/index.md @eread
+/doc/administration/auth/ldap/google_secure_ldap.md @eread
+/doc/administration/auth/jwt.md @eread
+/doc/administration/auth/ldap/ldap-troubleshooting.md @eread
+/doc/administration/auth/ldap/ldap_synchronization.md @eread
+/doc/administration/auth/ldap/index.md @eread
+/doc/administration/auth/oidc.md @eread
+/doc/administration/auth/smartcard.md @eread
+/doc/administration/cicd.md @marcel.amirault
+/doc/administration/clusters/kas.md @marcia
+/doc/administration/compliance.md @eread
+/doc/administration/configure.md @axil
+/doc/administration/consul.md @axil
+/doc/administration/docs_self_host.md @axil
+/doc/administration/encrypted_configuration.md @axil
+/doc/administration/environment_variables.md @axil
+/doc/administration/external_pipeline_validation.md @marcel.amirault
+/doc/administration/feature_flags.md @axil
+/doc/administration/file_hooks.md @aqualls
/doc/administration/geo/ @axil
+/doc/administration/git_protocol.md @aqualls
/doc/administration/gitaly/ @eread
-/doc/administration/lfs/ @aqualls
+/doc/administration/housekeeping.md @axil
+/doc/administration/incoming_email.md @msedlakjakubowski
+/doc/administration/index.md @axil
+/doc/administration/instance_limits.md @axil
+/doc/administration/instance_review.md @kpaizee
+/doc/administration/integration/kroki.md @kpaizee
+/doc/administration/integration/mailgun.md @kpaizee
+/doc/administration/integration/plantuml.md @aqualls
+/doc/administration/integration/terminal.md @kpaizee
+/doc/administration/invalidate_markdown_cache.md @msedlakjakubowski
+/doc/administration/issue_closing_pattern.md @aqualls
+/doc/administration/job_artifacts.md @eread
+/doc/administration/job_logs.md @sselhorn
+/doc/administration/lfs/index.md @aqualls
+/doc/administration/libravatar.md @axil
+/doc/administration/load_balancer.md @axil
+/doc/administration/logs.md @ngaskill
+/doc/administration/maintenance_mode/index.md @axil
+/doc/administration/merge_request_diffs.md @aqualls
/doc/administration/monitoring/ @ngaskill
-/doc/administration/operations/ @axil @eread @marcia
+/doc/administration/nfs.md @axil
+/doc/administration/object_storage.md @axil
+/doc/administration/operations/ @axil
+/doc/administration/operations/sidekiq_memory_killer.md @marcia
+/doc/administration/package_information/ @axil
/doc/administration/packages/ @ngaskill
-/doc/administration/pages/ @rdickenson @kpaizee
+/doc/administration/pages/ @rdickenson
+/doc/administration/polling.md @axil
/doc/administration/postgresql/ @marcia
-/doc/administration/raketasks/ @axil @eread
+/doc/administration/pseudonymizer.md @axil
+/doc/administration/raketasks/ @axil
+/doc/administration/read_only_gitlab.md @axil
/doc/administration/redis/ @axil
/doc/administration/reference_architectures/ @axil
-/doc/administration/snippets/ @aqualls
-/doc/administration/troubleshooting @axil @marcia @eread
-/doc/api/graphql/ @msedlakjakubowski @kpaizee
-/doc/api/graphql/reference/ @kpaizee
-/doc/api/group_activity_analytics.md @fneill
-/doc/api/vulnerabilities.md @fneill
-/doc/ci/ @marcel.amirault @sselhorn
-/doc/ci/environments/ @rdickenson
-/doc/ci/services/ @sselhorn
-/doc/ci/test_cases/ @msedlakjakubowski
-/doc/development/ @marcia
-/doc/development/documentation/ @cnorris @dianalogan
-/doc/development/i18n/ @ngaskill
-/doc/development/value_stream_analytics.md @fneill
-/doc/gitlab-basics/ @aqualls
-/doc/install/ @axil
-/doc/operations/ @ngaskill @rdickenson
-/doc/push_rules/ @aqualls
-/doc/security/ @eread
-/doc/ssh/ @eread
-/doc/subscriptions/ @sselhorn
-/doc/topics/autodevops/ @marcia
-/doc/topics/git/ @aqualls
-/doc/update/ @axil @marcia
-/doc/user/analytics/ @fneill @ngaskill
-/doc/user/application_security/ @rdickenson
-/doc/user/application_security/container_scanning/ @ngaskill
-/doc/user/application_security/cluster_image_scanning/ @ngaskill
-/doc/user/application_security/cve_id_request.md @fneill
-/doc/user/application_security/security_dashboard @fneill
-/doc/user/application_security/vulnerabilities @fneill
-/doc/user/application_security/vulnerability_report @fneill
-/doc/user/clusters/ @marcia
-/doc/user/compliance/ @rdickenson @eread
-/doc/user/group/ @msedlakjakubowski
-/doc/user/group/devops_adoption/ @fneill
-/doc/user/group/epics/ @msedlakjakubowski
-/doc/user/group/insights/ @fneill
-/doc/user/group/iterations/ @msedlakjakubowski
-/doc/user/group/roadmap/ @msedlakjakubowski
-/doc/user/group/value_stream_analytics/ @fneill
-/doc/user/infrastructure/ @marcia
-/doc/user/packages/ @ngaskill
-/doc/user/packages/infrastructure_registry/ @marcia
-/doc/user/packages/terraform_module_registry/ @marcia
-/doc/user/profile/ @msedlakjakubowski @eread
-/doc/user/project/ @aqualls @rdickenson @eread @msedlakjakubowski @ngaskill
-/doc/user/project/clusters/ @marcia
-/doc/user/project/import/ @ngaskill @msedlakjakubowski
-/doc/user/project/issues/ @msedlakjakubowski
-/doc/user/project/merge_requests/ @aqualls @eread
-/doc/user/project/milestones/ @msedlakjakubowski
-/doc/user/project/pages/ @rdickenson
-/doc/user/project/repository/ @aqualls
-/doc/user/project/settings/ @aqualls @eread
-/doc/user/project/static_site_editor/index.md @aqualls
-/doc/user/project/web_ide/index.md @aqualls
-/doc/user/project/wiki/index.md @aqualls
-/doc/user/search/ @marcia @aqualls
-/doc/user/workspace/ @fneill
-
-[Docs Create]
-/doc/administration/file_hooks.md @aqualls
-/doc/administration/git_protocol.md @aqualls
-/doc/administration/invalidate_markdown_cache.md @aqualls
-/doc/administration/issue_closing_pattern.md @aqualls
-/doc/administration/merge_request_diffs.md @aqualls
-/doc/administration/repository_checks.md @aqualls
+/doc/administration/reply_by_email_postfix_setup.md @axil
+/doc/administration/reply_by_email.md @msedlakjakubowski
+/doc/administration/repository_checks.md @eread
+/doc/administration/repository_storage_paths.md @eread
+/doc/administration/repository_storage_types.md @eread
+/doc/administration/restart_gitlab.md @axil
+/doc/administration/server_hooks.md @eread
+/doc/administration/sidekiq.md @axil
+/doc/administration/smime_signing_email.md @axil
+/doc/administration/snippets/index.md @aqualls
/doc/administration/static_objects_external_storage.md @aqualls
-/doc/api/access_requests.md @aqualls
+/doc/administration/terraform_state.md @marcia
+/doc/administration/timezone.md @axil
+/doc/administration/troubleshooting/ @axil
+/doc/administration/troubleshooting/group_saml_scim.md @eread
+/doc/administration/troubleshooting/postgresql.md @marcia
+/doc/administration/uploads.md @axil
+/doc/administration/user_settings.md @eread
+/doc/administration/whats-new.md @kpaizee
+/doc/administration/wikis/index.md @aqualls
+/doc/api/access_requests.md @eread
+/doc/api/admin_sidekiq_queues.md @axil
+/doc/api/api_resources.md @kpaizee
+/doc/api/appearance.md @eread
+/doc/api/applications.md @eread
+/doc/api/audit_events.md @eread
+/doc/api/avatar.md @eread
+/doc/api/award_emoji.md @msedlakjakubowski
+/doc/api/boards.md @msedlakjakubowski
/doc/api/branches.md @aqualls
+/doc/api/broadcast_messages.md @kpaizee
+/doc/api/bulk_imports.md @ngaskill
/doc/api/commits.md @aqualls
+/doc/api/container_registry.md @ngaskill
+/doc/api/custom_attributes.md @kpaizee
+/doc/api/dependencies.md @rdickenson
+/doc/api/dependency_proxy.md @ngaskill
+/doc/api/deploy_keys.md @rdickenson
+/doc/api/deploy_tokens.md @rdickenson
+/doc/api/deployments.md @rdickenson
/doc/api/discussions.md @aqualls
+/doc/api/dora/metrics.md @fneill
+/doc/api/dora4_project_analytics.md @fneill
+/doc/api/environments.md @rdickenson
+/doc/api/epic_issues.md @msedlakjakubowski
+/doc/api/epic_links.md @msedlakjakubowski
+/doc/api/epics.md @msedlakjakubowski
+/doc/api/error_tracking.md @ngaskill
+/doc/api/events.md @eread
+/doc/api/experiments.md @kpaizee
+/doc/api/feature_flag_specs.md @rdickenson
+/doc/api/feature_flag_user_lists.md @rdickenson
+/doc/api/feature_flags_legacy.md @rdickenson
+/doc/api/feature_flags.md @rdickenson
+/doc/api/features.md @rdickenson
+/doc/api/freeze_periods.md @rdickenson
+/doc/api/geo_nodes.md @axil
+/doc/api/graphql/ @kpaizee
+/doc/api/graphql/custom_emoji.md @msedlakjakubowski
+/doc/api/graphql/sample_issue_boards.md @msedlakjakubowski
+/doc/api/group_activity_analytics.md @fneill
+/doc/api/group_badges.md @eread
+/doc/api/group_boards.md @msedlakjakubowski
+/doc/api/group_clusters.md @marcia
+/doc/api/group_import_export.md @ngaskill
+/doc/api/group_iterations.md @msedlakjakubowski
+/doc/api/group_labels.md @msedlakjakubowski
+/doc/api/group_level_variables.md @marcel.amirault
+/doc/api/group_milestones.md @msedlakjakubowski
+/doc/api/group_protected_environments.md @rdickenson
+/doc/api/group_relations_export.md @ngaskill
+/doc/api/group_repository_storage_moves.md @aqualls
/doc/api/group_wikis.md @aqualls
+/doc/api/groups.md @eread
+/doc/api/import.md @ngaskill
+/doc/api/index.md @kpaizee
+/doc/api/instance_clusters.md @marcia
+/doc/api/instance_level_ci_variables.md @marcel.amirault
+/doc/api/integrations.md @kpaizee
+/doc/api/invitations.md @kpaizee
+/doc/api/issue_links.md @msedlakjakubowski
+/doc/api/issues_statistics.md @msedlakjakubowski
+/doc/api/issues.md @msedlakjakubowski
+/doc/api/iterations.md @msedlakjakubowski
+/doc/api/job_artifacts.md @eread
+/doc/api/jobs.md @marcel.amirault
/doc/api/keys.md @aqualls
+/doc/api/labels.md @msedlakjakubowski
+/doc/api/license.md @kpaizee
+/doc/api/lint.md @marcel.amirault
+/doc/api/managed_licenses.md @kpaizee
/doc/api/markdown.md @aqualls
+/doc/api/members.md @eread
/doc/api/merge_request_approvals.md @aqualls
/doc/api/merge_request_context_commits.md @aqualls
/doc/api/merge_requests.md @aqualls
+/doc/api/merge_trains.md @marcel.amirault
+/doc/api/metrics_dashboard_annotations.md @ngaskill
+/doc/api/metrics_user_starred_dashboards.md @ngaskill
+/doc/api/milestones.md @msedlakjakubowski
+/doc/api/namespaces.md @eread
+/doc/api/notes.md @msedlakjakubowski
+/doc/api/notification_settings.md @msedlakjakubowski
+/doc/api/oauth2.md @eread
+/doc/api/openapi/openapi_interactive.md @kpaizee
+/doc/api/packages.md @ngaskill
+/doc/api/packages/ @ngaskill
+/doc/api/pages_domains.md @rdickenson
+/doc/api/pages.md @rdickenson
+/doc/api/personal_access_tokens.md @eread
+/doc/api/pipeline_schedules.md @marcel.amirault
+/doc/api/pipeline_triggers.md @marcel.amirault
+/doc/api/pipelines.md @marcel.amirault
+/doc/api/plan_limits.md @eread
/doc/api/project_aliases.md @aqualls
/doc/api/project_badges.md @aqualls
+/doc/api/project_clusters.md @marcia
/doc/api/project_import_export.md @aqualls
-/doc/api/project_level_variables.md @aqualls
+/doc/api/project_level_variables.md @marcel.amirault
+/doc/api/project_relations_export.md @ngaskill
+/doc/api/project_repository_storage_moves.md @eread
/doc/api/project_snippets.md @aqualls
/doc/api/project_statistics.md @aqualls
/doc/api/project_templates.md @aqualls
/doc/api/project_vulnerabilities.md @aqualls
+/doc/api/projects.md @msedlakjakubowski
/doc/api/protected_branches.md @aqualls
+/doc/api/protected_environments.md @rdickenson
/doc/api/protected_tags.md @aqualls
+/doc/api/releases/index.md @rdickenson
+/doc/api/releases/links.md @rdickenson
/doc/api/remote_mirrors.md @aqualls
/doc/api/repositories.md @aqualls
/doc/api/repository_files.md @aqualls
/doc/api/repository_submodules.md @aqualls
+/doc/api/resource_access_tokens.md @eread
+/doc/api/resource_groups.md @rdickenson
+/doc/api/resource_iteration_events.md @msedlakjakubowski
+/doc/api/resource_label_events.md @eread
+/doc/api/resource_milestone_events.md @msedlakjakubowski
+/doc/api/resource_state_events.md @msedlakjakubowski
+/doc/api/resource_weight_events.md @msedlakjakubowski
+/doc/api/runners.md @sselhorn
+/doc/api/scim.md @eread
/doc/api/search.md @aqualls
-/doc/api/services.md @aqualls
+/doc/api/settings.md @eread
+/doc/api/sidekiq_metrics.md @axil
+/doc/api/snippet_repository_storage_moves.md @aqualls
/doc/api/snippets.md @aqualls
+/doc/api/statistics.md @eread
+/doc/api/status_checks.md @eread
/doc/api/suggestions.md @aqualls
+/doc/api/system_hooks.md @kpaizee
/doc/api/tags.md @aqualls
-/doc/api/visual_review_discussions.md @aqualls
+/doc/api/templates/dockerfiles.md @aqualls
+/doc/api/templates/gitignores.md @aqualls
+/doc/api/templates/gitlab_ci_ymls.md @marcel.amirault
+/doc/api/templates/licenses.md @rdickenson
+/doc/api/todos.md @msedlakjakubowski
+/doc/api/topics.md @fneill
+/doc/api/usage_data.md @fneill
+/doc/api/users.md @eread
+/doc/api/v3_to_v4.md @kpaizee
+/doc/api/version.md @kpaizee
+/doc/api/visual_review_discussions.md @eread
+/doc/api/vulnerabilities.md @fneill
+/doc/api/vulnerability_exports.md @fneill
+/doc/api/vulnerability_findings.md @fneill
/doc/api/wikis.md @aqualls
-/doc/intro/index.md @aqualls
+/doc/architecture/blueprints/container_registry_metadata_database/index.md @ngaskill
+/doc/architecture/blueprints/database/scalability/patterns/ @marcia
+/doc/architecture/blueprints/gitlab_to_kubernetes_communication/index.md @marcia
+/doc/ci/caching/index.md @marcel.amirault
+/doc/ci/chatops/index.md @marcia
+/doc/ci/ci_cd_for_external_repos/ @marcel.amirault
+/doc/ci/cloud_deployment/ecs/quick_start_guide.md @rdickenson
+/doc/ci/cloud_deployment/index.md @rdickenson
+/doc/ci/directed_acyclic_graph/index.md @marcel.amirault
+/doc/ci/docker/index.md @marcel.amirault
+/doc/ci/docker/using_docker_build.md @marcel.amirault
+/doc/ci/docker/using_docker_images.md @sselhorn
+/doc/ci/docker/using_kaniko.md @marcel.amirault
+/doc/ci/enable_or_disable_ci.md @marcel.amirault
+/doc/ci/environments/ @rdickenson
+/doc/ci/examples/authenticating-with-hashicorp-vault/index.md @rdickenson
+/doc/ci/examples/deployment/composer-npm-deploy.md @rdickenson
+/doc/ci/examples/deployment/index.md @rdickenson
+/doc/ci/examples/end_to_end_testing_webdriverio/index.md @eread
+/doc/ci/examples/index.md @marcel.amirault
+/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md @marcel.amirault
+/doc/ci/examples/php.md @marcel.amirault
+/doc/ci/examples/semantic-release.md @ngaskill
+/doc/ci/git_submodules.md @marcel.amirault
+/doc/ci/index.md @marcel.amirault
+/doc/ci/interactive_web_terminal/index.md @sselhorn
+/doc/ci/introduction/index.md @marcel.amirault
+/doc/ci/jobs/ci_job_token.md @marcel.amirault
+/doc/ci/jobs/index.md @marcel.amirault
+/doc/ci/jobs/job_control.md @marcel.amirault
+/doc/ci/large_repositories/index.md @sselhorn
+/doc/ci/lint.md @marcel.amirault
+/doc/ci/metrics_reports.md @eread
+/doc/ci/migration/circleci.md @marcel.amirault
+/doc/ci/migration/jenkins.md @marcel.amirault
+/doc/ci/pipeline_editor/index.md @marcel.amirault
+/doc/ci/pipelines/ @marcel.amirault
+/doc/ci/pipelines/job_artifacts.md @eread
+/doc/ci/pipelines/pipeline_artifacts.md @eread
+/doc/ci/quick_start/index.md @marcel.amirault
+/doc/ci/resource_groups/index.md @rdickenson
+/doc/ci/review_apps/index.md @eread
+/doc/ci/runners/ @sselhorn
+/doc/ci/secrets/index.md @marcia
+/doc/ci/services/ @sselhorn
+/doc/ci/ssh_keys/index.md @marcel.amirault
+/doc/ci/test_cases/index.md @msedlakjakubowski
+/doc/ci/triggers/index.md @marcel.amirault
+/doc/ci/troubleshooting.md @marcel.amirault
+/doc/ci/unit_test_reports.md @eread
+/doc/ci/variables/ @marcel.amirault
+/doc/ci/yaml/ @marcel.amirault
+/doc/ci/yaml/artifacts_reports.md @eread
+/doc/development/adding_database_indexes.md @marcia
+/doc/development/application_limits.md @axil
+/doc/development/approval_rules.md @aqualls
+/doc/development/audit_event_guide/index.md @eread
+/doc/development/auto_devops.md @marcia
+/doc/development/avoiding_downtime_in_migrations.md @marcia
+/doc/development/backend/ruby_style_guide.md @marcia
+/doc/development/background_migrations.md @marcia
+/doc/development/build_test_package.md @axil
+/doc/development/bulk_import.md @ngaskill
+/doc/development/cascading_settings.md @eread
+/doc/development/chatops_on_gitlabcom.md @marcia
+/doc/development/cicd/cicd_reference_documentation_guide.md @marcel.amirault
+/doc/development/cicd/index.md @marcel.amirault
+/doc/development/cicd/templates.md @marcel.amirault
+/doc/development/code_intelligence/index.md @aqualls
+/doc/development/contributing/ @marcia
+/doc/development/creating_enums.md @marcia
+/doc/development/database_debugging.md @marcia
+/doc/development/database_query_comments.md @marcia
+/doc/development/database_review.md @marcia
+/doc/development/database/ @marcia
+/doc/development/db_dump.md @marcia
+/doc/development/developing_with_solargraph.md @aqualls
+/doc/development/distributed_tracing.md @ngaskill
+/doc/development/documentation/feature_flags.md @marcia
+/doc/development/documentation/graphql_styleguide.md @marcia
+/doc/development/documentation/index.md @cnorris
+/doc/development/documentation/redirects.md @cnorris
+/doc/development/documentation/restful_api_styleguide.md @marcia
+/doc/development/documentation/review_apps.md @cnorris
+/doc/development/documentation/structure.md @sselhorn
+/doc/development/documentation/styleguide/index.md @sselhorn
+/doc/development/documentation/styleguide/word_list.md @sselhorn
+/doc/development/documentation/testing.md @cnorris
+/doc/development/elasticsearch.md @marcia
+/doc/development/experiment_guide/ @kpaizee
+/doc/development/export_csv.md @ngaskill
+/doc/development/fe_guide/content_editor.md @aqualls
+/doc/development/fe_guide/dark_mode.md @marcia
+/doc/development/fe_guide/graphql.md @marcia
+/doc/development/fe_guide/source_editor.md @aqualls
+/doc/development/feature_categorization/index.md @marcia
+/doc/development/feature_flags/controls.md @marcia
+/doc/development/feature_flags/index.md @marcia
+/doc/development/filtering_by_label.md @msedlakjakubowski
+/doc/development/foreign_keys.md @marcia
+/doc/development/geo.md @axil
+/doc/development/geo/framework.md @axil
+/doc/development/git_object_deduplication.md @eread
+/doc/development/gitaly.md @eread
+/doc/development/graphql_guide/batchloader.md @marcia
+/doc/development/graphql_guide/graphql_pro.md @kpaizee
+/doc/development/graphql_guide/index.md @kpaizee
+/doc/development/graphql_guide/pagination.md @kpaizee
+/doc/development/hash_indexes.md @marcia
+/doc/development/i18n/ @ngaskill
+/doc/development/image_scaling.md @marcia
+/doc/development/import_export.md @ngaskill
+/doc/development/index.md @marcia
+/doc/development/insert_into_tables_in_batches.md @marcia
+/doc/development/integrations/codesandbox.md @marcia
+/doc/development/integrations/jenkins.md @kpaizee
+/doc/development/integrations/jira_connect.md @kpaizee
+/doc/development/integrations/secure_partner_integration.md @rdickenson
+/doc/development/integrations/secure.md @ngaskill
+/doc/development/internal_api/ @aqualls
+/doc/development/internal_users.md @marcia
+/doc/development/issuable-like-models.md @msedlakjakubowski
+/doc/development/issue_types.md @msedlakjakubowski
+/doc/development/iterating_tables_in_batches.md @marcia
+/doc/development/kubernetes.md @marcia
+/doc/development/lfs.md @aqualls
+/doc/development/licensed_feature_availability.md @sselhorn
+/doc/development/logging.md @ngaskill
+/doc/development/maintenance_mode.md @axil
+/doc/development/new_fe_guide/modules/widget_extensions.md @aqualls
+/doc/development/new_fe_guide/tips.md @marcia
+/doc/development/omnibus.md @axil
+/doc/development/ordering_table_columns.md @marcia
+/doc/development/packages.md @ngaskill
+/doc/development/permissions.md @eread
+/doc/development/policies.md @eread
+/doc/development/prometheus_metrics.md @ngaskill
+/doc/development/query_performance.md @marcia
+/doc/development/real_time.md @msedlakjakubowski
+/doc/development/secure_coding_guidelines.md @marcia
+/doc/development/serializing_data.md @marcia
+/doc/development/service_ping/ @fneill
+/doc/development/snowplow/ @fneill
+/doc/development/sql.md @marcia
+/doc/development/stage_group_dashboards.md @marcia
+/doc/development/swapping_tables.md @marcia
+/doc/development/testing_guide/best_practices.md @marcia
+/doc/development/testing_guide/end_to_end/best_practices.md @marcia
+/doc/development/understanding_explain_plans.md @marcia
+/doc/development/value_stream_analytics.md @fneill
+/doc/development/verifying_database_capabilities.md @marcia
+/doc/development/wikis.md @aqualls
+/doc/development/work_items.md @msedlakjakubowski
+/doc/development/work_items_widgets.md @msedlakjakubowski
+/doc/downgrade_ee_to_ce/index.md @axil
+/doc/gitlab-basics/add-file.md @aqualls
+/doc/gitlab-basics/command-line-commands.md @aqualls
+/doc/gitlab-basics/create-branch.md @aqualls
+/doc/gitlab-basics/feature_branch_workflow.md @aqualls
+/doc/gitlab-basics/index.md @aqualls
+/doc/gitlab-basics/start-using-git.md @aqualls
+/doc/install/ @axil
+/doc/integration/ @kpaizee
+/doc/integration/elasticsearch.md @marcia
+/doc/integration/gitpod.md @aqualls
+/doc/integration/kerberos.md @eread
+/doc/integration/mattermost/index.md @axil
+/doc/integration/oauth_provider.md @eread
+/doc/integration/saml.md @eread
+/doc/integration/security_partners/index.md @rdickenson
+/doc/integration/sourcegraph.md @aqualls
+/doc/integration/vault.md @rdickenson
+/doc/operations/ @ngaskill
+/doc/operations/feature_flags.md @rdickenson
+/doc/operations/product_analytics.md @fneill
+/doc/policy/ @axil
+/doc/public_access/public_access.md @fneill
+/doc/push_rules/push_rules.md @aqualls
+/doc/raketasks/ @axil
+/doc/raketasks/generate_sample_prometheus_data.md @ngaskill
+/doc/raketasks/migrate_snippets.md @aqualls
+/doc/raketasks/spdx.md @rdickenson
+/doc/raketasks/x509_signatures.md @aqualls
+/doc/security/ @eread
+/doc/ssh/index.md @eread
+/doc/subscriptions/ @sselhorn
+/doc/system_hooks/system_hooks.md @kpaizee
+/doc/topics/authentication/index.md @eread
+/doc/topics/autodevops/customize.md @marcia
+/doc/topics/autodevops/ @marcia
+/doc/topics/git/ @aqualls
/doc/topics/gitlab_flow.md @aqualls
+/doc/topics/offline/ @axil
+/doc/topics/plan_and_track.md @msedlakjakubowski
+/doc/update/ @axil
+/doc/update/mysql_to_postgresql.md @marcia
+/doc/update/upgrading_postgresql_using_slony.md @marcia
+/doc/user/admin_area/analytics/ @fneill
+/doc/user/admin_area/broadcast_messages.md @kpaizee
+/doc/user/admin_area/credentials_inventory.md @eread
+/doc/user/admin_area/custom_project_templates.md @ngaskill
+/doc/user/admin_area/diff_limits.md @aqualls
+/doc/user/admin_area/geo_nodes.md @axil
+/doc/user/admin_area/labels.md @msedlakjakubowski
+/doc/user/admin_area/license.md @kpaizee
+/doc/user/admin_area/merge_requests_approvals.md @aqualls
+/doc/user/admin_area/moderate_users.md @eread
+/doc/user/admin_area/monitoring/background_migrations.md @marcia
+/doc/user/admin_area/monitoring/health_check.md @ngaskill
+/doc/user/admin_area/review_abuse_reports.md @eread
/doc/user/admin_area/settings/account_and_limit_settings.md @aqualls
+/doc/user/admin_area/settings/continuous_integration.md @marcel.amirault
+/doc/user/admin_area/settings/deprecated_api_rate_limits.md @aqualls
+/doc/user/admin_area/settings/email.md @msedlakjakubowski
+/doc/user/admin_area/settings/external_authorization.md @eread
+/doc/user/admin_area/settings/files_api_rate_limits.md @aqualls
+/doc/user/admin_area/settings/git_lfs_rate_limits.md @aqualls
+/doc/user/admin_area/settings/gitaly_timeouts.md @eread
+/doc/user/admin_area/settings/import_export_rate_limits.md @ngaskill
+/doc/user/admin_area/settings/index.md @aqualls
/doc/user/admin_area/settings/instance_template_repository.md @aqualls
-/doc/user/admin_area/settings/project_integration_management.md @aqualls
+/doc/user/admin_area/settings/package_registry_rate_limits.md @ngaskill
+/doc/user/admin_area/settings/project_integration_management.md @kpaizee
/doc/user/admin_area/settings/push_event_activities_limit.md @aqualls
+/doc/user/admin_area/settings/rate_limit_on_issues_creation.md @msedlakjakubowski
+/doc/user/admin_area/settings/rate_limit_on_notes_creation.md @msedlakjakubowski
/doc/user/admin_area/settings/visibility_and_access_controls.md @aqualls
+/doc/user/analytics/ci_cd_analytics.md @rdickenson
+/doc/user/analytics/ @fneill
+/doc/user/application_security/ @rdickenson
+/doc/user/application_security/cluster_image_scanning/index.md @ngaskill
+/doc/user/application_security/container_scanning/index.md @ngaskill
+/doc/user/application_security/cve_id_request.md @fneill
+/doc/user/application_security/policies/index.md @ngaskill
+/doc/user/application_security/security_dashboard/index.md @fneill
+/doc/user/application_security/threat_monitoring/index.md @ngaskill
+/doc/user/application_security/vulnerabilities/ @fneill
+/doc/user/application_security/vulnerability_report/index.md @fneill
/doc/user/asciidoc.md @aqualls
-/doc/user/index.md @aqualls
+/doc/user/award_emojis.md @msedlakjakubowski
+/doc/user/clusters/ @marcia
+/doc/user/compliance/compliance_report/index.md @eread
+/doc/user/compliance/index.md @eread
+/doc/user/compliance/license_compliance/index.md @rdickenson
+/doc/user/discussions/index.md @aqualls
+/doc/user/feature_flags.md @marcia
+/doc/user/group/clusters/index.md @marcia
+/doc/user/group/contribution_analytics/index.md @fneill
+/doc/user/group/custom_project_templates.md @ngaskill
+/doc/user/group/devops_adoption/index.md @fneill
+/doc/user/group/epics/epic_boards.md @msedlakjakubowski
+/doc/user/group/epics/index.md @msedlakjakubowski
+/doc/user/group/epics/manage_epics.md @msedlakjakubowski
+/doc/user/group/import/index.md @ngaskill
+/doc/user/group/index.md @eread
+/doc/user/group/insights/index.md @fneill
+/doc/user/group/issues_analytics/index.md @msedlakjakubowski
+/doc/user/group/iterations/index.md @msedlakjakubowski
+/doc/user/group/repositories_analytics/index.md @eread
+/doc/user/group/roadmap/index.md @msedlakjakubowski
+/doc/user/group/saml_sso/group_managed_accounts.md @eread
+/doc/user/group/saml_sso/index.md @eread
+/doc/user/group/saml_sso/scim_setup.md @eread
+/doc/user/group/settings/import_export.md @ngaskill
+/doc/user/group/subgroups/index.md @eread
+/doc/user/group/value_stream_analytics/index.md @fneill
+/doc/user/infrastructure/clusters/ @marcia
+/doc/user/infrastructure/clusters/manage/clusters_health.md @marcia
+/doc/user/infrastructure/clusters/manage/management_project_applications/apparmor.md @ngaskill
+/doc/user/infrastructure/clusters/manage/management_project_applications/certmanager.md @marcia
+/doc/user/infrastructure/clusters/manage/management_project_applications/cilium.md @ngaskill
+/doc/user/infrastructure/clusters/manage/management_project_applications/elasticstack.md @ngaskill
+/doc/user/infrastructure/clusters/manage/management_project_applications/falco.md @ngaskill
+/doc/user/infrastructure/clusters/manage/management_project_applications/fluentd.md @ngaskill
+/doc/user/infrastructure/clusters/manage/management_project_applications/ingress.md @marcia
+/doc/user/infrastructure/clusters/manage/management_project_applications/prometheus.md @ngaskill
+/doc/user/infrastructure/clusters/manage/management_project_applications/runner.md @sselhorn
+/doc/user/infrastructure/clusters/manage/management_project_applications/sentry.md @ngaskill
+/doc/user/infrastructure/clusters/manage/management_project_applications/vault.md @marcia
+/doc/user/infrastructure/iac/ @marcia
+/doc/user/infrastructure/index.md @marcia
/doc/user/markdown.md @aqualls
+/doc/user/packages/ @ngaskill
+/doc/user/packages/infrastructure_registry/index.md @marcia
+/doc/user/packages/terraform_module_registry/index.md @marcia
+/doc/user/permissions.md @eread
+/doc/user/profile/ @eread
+/doc/user/profile/notifications.md @msedlakjakubowski
/doc/user/project/autocomplete_characters.md @aqualls
/doc/user/project/badges.md @aqualls
+/doc/user/project/clusters/ @marcia
+/doc/user/project/clusters/kubernetes_pod_logs.md @ngaskill
+/doc/user/project/clusters/protect/ @ngaskill
/doc/user/project/code_intelligence.md @aqualls
/doc/user/project/code_owners.md @aqualls
+/doc/user/project/deploy_boards.md @rdickenson
+/doc/user/project/deploy_keys/index.md @rdickenson
+/doc/user/project/deploy_tokens/index.md @rdickenson
+/doc/user/project/description_templates.md @msedlakjakubowski
/doc/user/project/file_lock.md @aqualls
/doc/user/project/git_attributes.md @aqualls
/doc/user/project/highlighting.md @aqualls
-/doc/user/project/index.md @aqualls
+/doc/user/project/import/ @ngaskill
+/doc/user/project/import/jira.md @msedlakjakubowski
+/doc/user/project/index.md @fneill
+/doc/user/project/integrations/ @kpaizee
+/doc/user/project/integrations/prometheus_library/ @ngaskill
+/doc/user/project/integrations/prometheus.md @ngaskill
+/doc/user/project/issue_board.md @msedlakjakubowski
+/doc/user/project/issues/ @msedlakjakubowski
+/doc/user/project/labels.md @msedlakjakubowski
+/doc/user/project/members/index.md @eread
+/doc/user/project/members/share_project_with_groups.md @fneill
+/doc/user/project/merge_requests/ @aqualls
+/doc/user/project/merge_requests/accessibility_testing.md @eread
+/doc/user/project/merge_requests/browser_performance_testing.md @eread
+/doc/user/project/merge_requests/code_quality.md @rdickenson
+/doc/user/project/merge_requests/csv_export.md @eread
+/doc/user/project/merge_requests/fail_fast_testing.md @eread
+/doc/user/project/merge_requests/load_performance_testing.md @eread
+/doc/user/project/merge_requests/status_checks.md @eread
+/doc/user/project/merge_requests/test_coverage_visualization.md @eread
+/doc/user/project/merge_requests/testing_and_reports_in_merge_requests.md @eread
+/doc/user/project/milestones/ @msedlakjakubowski
+/doc/user/project/pages/ @rdickenson
/doc/user/project/protected_branches.md @aqualls
/doc/user/project/protected_tags.md @aqualls
/doc/user/project/push_options.md @aqualls
-/doc/user/project/settings/import_export.md @aqualls
+/doc/user/project/quick_actions.md @msedlakjakubowski
+/doc/user/project/releases/index.md @rdickenson
+/doc/user/project/releases/release_cli.md @rdickenson
+/doc/user/project/repository/ @aqualls
+/doc/user/project/repository/reducing_the_repo_size_using_git.md @eread
+/doc/user/project/requirements/index.md @msedlakjakubowski
+/doc/user/project/service_desk.md @msedlakjakubowski
+/doc/user/project/settings/import_export.md @ngaskill
+/doc/user/project/settings/index.md @fneill
+/doc/user/project/settings/project_access_tokens.md @eread
+/doc/user/project/static_site_editor/index.md @aqualls
+/doc/user/project/time_tracking.md @msedlakjakubowski
+/doc/user/project/web_ide/index.md @aqualls
+/doc/user/project/wiki/group.md @aqualls
+/doc/user/project/wiki/index.md @aqualls
+/doc/user/project/working_with_projects.md @fneill
+/doc/user/reserved_names.md @fneill
+/doc/user/search/advanced_search.md @marcia
+/doc/user/search/index.md @aqualls
/doc/user/snippets.md @aqualls
-
-[Docs Ecosystem]
-/doc/administration/integration/ @kpaizee
-/doc/integration/ @kpaizee
-/doc/user/project/integrations/ @kpaizee
-/doc/user/project/integrations/prometheus_library/ @ngaskill
-
-[Docs Growth]
-/doc/administration/instance_review.md @kpaizee
-/doc/api/invitations.md @kpaizee
-/doc/api/experiments.md @kpaizee
-/doc/development/experiment_guide/ @kpaizee
-/doc/development/snowplow/ @fneill
-/doc/development/service_ping/ @fneill
-/doc/user/admin_area/license.md @kpaizee
+/doc/user/tasks.md @msedlakjakubowski
+/doc/user/todos.md @msedlakjakubowski
+/doc/user/usage_quotas.md @sselhorn
+/doc/user/workspace/index.md @fneill
diff --git a/.rubocop_todo/rails/save_bang.yml b/.rubocop_todo/rails/save_bang.yml
index 15361fd6743..ff9b0c9bbc8 100644
--- a/.rubocop_todo/rails/save_bang.yml
+++ b/.rubocop_todo/rails/save_bang.yml
@@ -2,15 +2,6 @@
Rails/SaveBang:
Exclude:
- ee/spec/lib/analytics/merge_request_metrics_calculator_spec.rb
- - ee/spec/models/protected_environment_spec.rb
- - ee/spec/models/repository_spec.rb
- - ee/spec/models/scim_identity_spec.rb
- - ee/spec/models/scim_oauth_access_token_spec.rb
- - ee/spec/models/upload_spec.rb
- - ee/spec/models/user_preference_spec.rb
- - ee/spec/models/visible_approvable_spec.rb
- - ee/spec/models/vulnerabilities/feedback_spec.rb
- - ee/spec/models/vulnerabilities/issue_link_spec.rb
- spec/lib/backup/manager_spec.rb
- spec/lib/gitlab/alerting/alert_spec.rb
- spec/lib/gitlab/analytics/cycle_analytics/records_fetcher_spec.rb
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index 5fa2f11b0dc..a0858417f82 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-7b20a6045e8d2a25c86633461c03b13353915643
+85efc2a008ed64cf8ed516aa43537712b478e139
diff --git a/app/assets/javascripts/badges/components/badge_list_row.vue b/app/assets/javascripts/badges/components/badge_list_row.vue
index d8525c15087..4c2b700c7ff 100644
--- a/app/assets/javascripts/badges/components/badge_list_row.vue
+++ b/app/assets/javascripts/badges/components/badge_list_row.vue
@@ -1,5 +1,5 @@
<script>
-import { GlLoadingIcon, GlButton, GlModalDirective } from '@gitlab/ui';
+import { GlLoadingIcon, GlButton, GlModalDirective, GlBadge } from '@gitlab/ui';
import { mapActions, mapState } from 'vuex';
import { s__ } from '~/locale';
import { PROJECT_BADGE } from '../constants';
@@ -11,6 +11,7 @@ export default {
Badge,
GlLoadingIcon,
GlButton,
+ GlBadge,
},
directives: {
GlModal: GlModalDirective,
@@ -49,7 +50,7 @@ export default {
/>
<div class="table-section section-30">
<label class="label-bold str-truncated mb-0">{{ badge.name }}</label>
- <span class="badge badge-pill">{{ badgeKindText }}</span>
+ <gl-badge size="sm">{{ badgeKindText }}</gl-badge>
</div>
<span class="table-section section-30 str-truncated">{{ badge.linkUrl }}</span>
<div class="table-section section-10 table-button-footer">
diff --git a/app/assets/javascripts/environments/components/deployment.vue b/app/assets/javascripts/environments/components/deployment.vue
index 77999bbe05b..60ea837736c 100644
--- a/app/assets/javascripts/environments/components/deployment.vue
+++ b/app/assets/javascripts/environments/components/deployment.vue
@@ -2,6 +2,7 @@
import { GlBadge, GlIcon, GlTooltipDirective as GlTooltip } from '@gitlab/ui';
import { __, s__ } from '~/locale';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import DeploymentStatusBadge from './deployment_status_badge.vue';
export default {
@@ -10,6 +11,7 @@ export default {
DeploymentStatusBadge,
GlBadge,
GlIcon,
+ TimeAgoTooltip,
},
directives: {
GlTooltip,
@@ -35,6 +37,9 @@ export default {
shortSha() {
return this.deployment?.commit?.shortId;
},
+ createdAt() {
+ return this.deployment?.createdAt;
+ },
},
i18n: {
latestBadge: s__('Deployment|Latest Deployed'),
@@ -69,6 +74,9 @@ export default {
:title="$options.i18n.copyButton"
size="small"
/>
+ <time-ago-tooltip v-if="createdAt" :time="createdAt" class="gl-ml-5!">
+ <template #default="{ timeAgo }"> <gl-icon name="calendar" /> {{ timeAgo }} </template>
+ </time-ago-tooltip>
</div>
</div>
</template>
diff --git a/app/assets/javascripts/google_cloud/components/service_accounts_form.vue b/app/assets/javascripts/google_cloud/components/service_accounts_form.vue
index e7a09668473..551783e6c50 100644
--- a/app/assets/javascripts/google_cloud/components/service_accounts_form.vue
+++ b/app/assets/javascripts/google_cloud/components/service_accounts_form.vue
@@ -1,9 +1,9 @@
<script>
-import { GlButton, GlFormGroup, GlFormSelect } from '@gitlab/ui';
+import { GlButton, GlFormGroup, GlFormSelect, GlFormCheckbox } from '@gitlab/ui';
import { __ } from '~/locale';
export default {
- components: { GlButton, GlFormGroup, GlFormSelect },
+ components: { GlButton, GlFormGroup, GlFormSelect, GlFormCheckbox },
props: {
gcpProjects: { required: true, type: Array },
environments: { required: true, type: Array },
@@ -19,6 +19,9 @@ export default {
environmentDescription: __('Generated service account is linked to the selected environment'),
submitLabel: __('Create service account'),
cancelLabel: __('Cancel'),
+ checkboxLabel: __(
+ 'I understand the responsibilities involved with managing service account keys',
+ ),
},
};
</script>
@@ -59,6 +62,11 @@ export default {
</option>
</gl-form-select>
</gl-form-group>
+ <gl-form-group>
+ <gl-form-checkbox name="confirmation" required>
+ {{ $options.i18n.checkboxLabel }}
+ </gl-form-checkbox>
+ </gl-form-group>
<div class="form-actions row">
<gl-button type="submit" category="primary" variant="confirm">
diff --git a/app/assets/javascripts/issues/list/components/issues_list_app.vue b/app/assets/javascripts/issues/list/components/issues_list_app.vue
index 8b15e801f02..3dc1a4c5143 100644
--- a/app/assets/javascripts/issues/list/components/issues_list_app.vue
+++ b/app/assets/javascripts/issues/list/components/issues_list_app.vue
@@ -644,6 +644,7 @@ export default {
:tabs="$options.IssuableListTabs"
:current-tab="state"
:tab-counts="tabCounts"
+ :truncate-counts="!isProject"
:issuables-loading="$apollo.queries.issues.loading"
:is-manual-ordering="isManualOrdering"
:show-bulk-edit-sidebar="showBulkEditSidebar"
diff --git a/app/assets/javascripts/lib/utils/constants.js b/app/assets/javascripts/lib/utils/constants.js
index 36c6545164e..379c57f3945 100644
--- a/app/assets/javascripts/lib/utils/constants.js
+++ b/app/assets/javascripts/lib/utils/constants.js
@@ -1,6 +1,7 @@
export const BYTES_IN_KIB = 1024;
export const DEFAULT_DEBOUNCE_AND_THROTTLE_MS = 250;
export const HIDDEN_CLASS = 'hidden';
+export const THOUSAND = 1000;
export const TRUNCATE_WIDTH_DEFAULT_WIDTH = 80;
export const TRUNCATE_WIDTH_DEFAULT_FONT_SIZE = 12;
diff --git a/app/assets/javascripts/lib/utils/number_utils.js b/app/assets/javascripts/lib/utils/number_utils.js
index f46263c0e4d..b0e31fe729b 100644
--- a/app/assets/javascripts/lib/utils/number_utils.js
+++ b/app/assets/javascripts/lib/utils/number_utils.js
@@ -1,5 +1,5 @@
import { sprintf, __ } from '~/locale';
-import { BYTES_IN_KIB } from './constants';
+import { BYTES_IN_KIB, THOUSAND } from './constants';
/**
* Function that allows a number with an X amount of decimals
@@ -86,6 +86,27 @@ export function numberToHumanSize(size, digits = 2) {
}
/**
+ * Converts a number to kilos or megas.
+ *
+ * For example:
+ * - 123 becomes 123
+ * - 123456 becomes 123.4k
+ * - 123456789 becomes 123.4m
+ *
+ * @param number Number to format
+ * @param digits The number of digits to appear after the decimal point
+ * @return {string} Formatted number
+ */
+export function numberToMetricPrefix(number, digits = 1) {
+ if (number < THOUSAND) {
+ return number.toString();
+ }
+ if (number < THOUSAND ** 2) {
+ return `${(number / THOUSAND).toFixed(digits)}k`;
+ }
+ return `${(number / THOUSAND ** 2).toFixed(digits)}m`;
+}
+/**
* A simple method that returns the value of a + b
* It seems unessesary, but when combined with a reducer it
* adds up all the values in an array.
diff --git a/app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue b/app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue
index da792b3a2aa..0de4cb2e59f 100644
--- a/app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue
+++ b/app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue
@@ -307,7 +307,12 @@ export default {
@close="handleClose"
>
<template #collapsed>
- <div v-if="isClassicSidebar" v-gl-tooltip class="sidebar-collapsed-icon">
+ <div
+ v-if="isClassicSidebar"
+ v-gl-tooltip.left.viewport
+ :title="attributeTypeTitle"
+ class="sidebar-collapsed-icon"
+ >
<gl-icon :size="16" :aria-label="attributeTypeTitle" :name="attributeTypeIcon" />
<span class="collapse-truncated-title">
{{ attributeTitle }}
diff --git a/app/assets/javascripts/sidebar/components/todo_toggle/sidebar_todo_widget.vue b/app/assets/javascripts/sidebar/components/todo_toggle/sidebar_todo_widget.vue
index a9c4203af22..8c56c3cbd57 100644
--- a/app/assets/javascripts/sidebar/components/todo_toggle/sidebar_todo_widget.vue
+++ b/app/assets/javascripts/sidebar/components/todo_toggle/sidebar_todo_widget.vue
@@ -177,19 +177,14 @@ export default {
/>
<gl-button
v-if="isClassicSidebar"
+ v-gl-tooltip.left.viewport
+ :title="tootltipTitle"
category="tertiary"
type="reset"
class="sidebar-collapsed-icon sidebar-collapsed-container gl-rounded-0! gl-shadow-none!"
@click.stop.prevent="toggleTodo"
>
- <gl-icon
- v-gl-tooltip.left.viewport
- :title="tootltipTitle"
- :size="16"
- :class="{ 'todo-undone': hasTodo }"
- :name="collapsedButtonIcon"
- :aria-label="collapsedButtonIcon"
- />
+ <gl-icon :class="{ 'todo-undone': hasTodo }" :name="collapsedButtonIcon" />
</gl-button>
</div>
</template>
diff --git a/app/assets/javascripts/vue_shared/issuable/list/components/issuable_list_root.vue b/app/assets/javascripts/vue_shared/issuable/list/components/issuable_list_root.vue
index 2f8401b45f0..a50f454f796 100644
--- a/app/assets/javascripts/vue_shared/issuable/list/components/issuable_list_root.vue
+++ b/app/assets/javascripts/vue_shared/issuable/list/components/issuable_list_root.vue
@@ -78,6 +78,11 @@ export default {
required: false,
default: null,
},
+ truncateCounts: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
currentTab: {
type: String,
required: true,
@@ -261,6 +266,7 @@ export default {
:tabs="tabs"
:tab-counts="tabCounts"
:current-tab="currentTab"
+ :truncate-counts="truncateCounts"
@click="$emit('click-tab', $event)"
>
<template #nav-actions>
diff --git a/app/assets/javascripts/vue_shared/issuable/list/components/issuable_tabs.vue b/app/assets/javascripts/vue_shared/issuable/list/components/issuable_tabs.vue
index 9bf54e98cc4..0691bc02b5c 100644
--- a/app/assets/javascripts/vue_shared/issuable/list/components/issuable_tabs.vue
+++ b/app/assets/javascripts/vue_shared/issuable/list/components/issuable_tabs.vue
@@ -1,5 +1,6 @@
<script>
import { GlTabs, GlTab, GlBadge } from '@gitlab/ui';
+import { numberToMetricPrefix } from '~/lib/utils/number_utils';
import { formatNumber } from '~/locale';
export default {
@@ -22,6 +23,11 @@ export default {
type: String,
required: true,
},
+ truncateCounts: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
methods: {
isTabActive(tabName) {
@@ -31,7 +37,7 @@ export default {
return Number.isInteger(this.tabCounts[tab.name]);
},
formatNumber(count) {
- return formatNumber(count);
+ return this.truncateCounts ? numberToMetricPrefix(count) : formatNumber(count);
},
},
};
diff --git a/app/finders/issues_finder.rb b/app/finders/issues_finder.rb
index de750b49c6a..a7eaaddd187 100644
--- a/app/finders/issues_finder.rb
+++ b/app/finders/issues_finder.rb
@@ -108,8 +108,14 @@ class IssuesFinder < IssuableFinder
if params.filter_by_no_due_date?
items.without_due_date
+ elsif params.filter_by_any_due_date?
+ items.with_due_date
elsif params.filter_by_overdue?
items.due_before(Date.today)
+ elsif params.filter_by_due_today?
+ items.due_today
+ elsif params.filter_by_due_tomorrow?
+ items.due_tomorrow
elsif params.filter_by_due_this_week?
items.due_between(Date.today.beginning_of_week, Date.today.end_of_week)
elsif params.filter_by_due_this_month?
diff --git a/app/finders/issues_finder/params.rb b/app/finders/issues_finder/params.rb
index 02b89f08f9e..57bfb35f1b8 100644
--- a/app/finders/issues_finder/params.rb
+++ b/app/finders/issues_finder/params.rb
@@ -10,6 +10,10 @@ class IssuesFinder
user_can_see_all_issues?
end
+ def filter_by_any_due_date?
+ due_date? && params[:due_date] == Issue::AnyDueDate.name
+ end
+
def filter_by_no_due_date?
due_date? && params[:due_date] == Issue::NoDueDate.name
end
@@ -18,6 +22,14 @@ class IssuesFinder
due_date? && params[:due_date] == Issue::Overdue.name
end
+ def filter_by_due_today?
+ due_date? && params[:due_date] == Issue::DueToday.name
+ end
+
+ def filter_by_due_tomorrow?
+ due_date? && params[:due_date] == Issue::DueTomorrow.name
+ end
+
def filter_by_due_this_week?
due_date? && params[:due_date] == Issue::DueThisWeek.name
end
diff --git a/app/graphql/types/ci/runner_type.rb b/app/graphql/types/ci/runner_type.rb
index ee2230eb24b..f4a3379c5ca 100644
--- a/app/graphql/types/ci/runner_type.rb
+++ b/app/graphql/types/ci/runner_type.rb
@@ -65,6 +65,8 @@ module Types
feature_flag: :graphql_ci_runner_executor
field :groups, ::Types::GroupType.connection_type, null: true,
description: 'Groups the runner is associated with. For group runners only.'
+ field :projects, ::Types::ProjectType.connection_type, null: true,
+ description: 'Projects the runner is associated with. For project runners only.'
def job_count
# We limit to 1 above the JOB_COUNT_LIMIT to indicate that more items exist after JOB_COUNT_LIMIT
@@ -94,31 +96,42 @@ module Types
end
end
end
+ # rubocop: enable CodeReuse/ActiveRecord
def groups
- BatchLoader::GraphQL.for(runner.id).batch(key: :runner_groups) do |runner_ids, loader, args|
- runner_and_namespace_ids =
- ::Ci::RunnerNamespace
- .where(runner_id: runner_ids)
- .pluck(:runner_id, :namespace_id)
+ return unless runner.group_type?
- group_ids_by_runner_id = runner_and_namespace_ids.group_by(&:first).transform_values { |v| v.pluck(1) }
- group_ids = runner_and_namespace_ids.pluck(1).uniq
+ batched_owners(::Ci::RunnerNamespace, Group, :runner_groups, :namespace_id)
+ end
- groups = Group.where(id: group_ids).index_by(&:id)
+ def projects
+ return unless runner.project_type?
- runner_ids.each do |runner_id|
- loader.call(runner_id, group_ids_by_runner_id[runner_id]&.map { |group_id| groups[group_id] })
- end
- end
+ batched_owners(::Ci::RunnerProject, Project, :runner_projects, :project_id)
end
- # rubocop: enable CodeReuse/ActiveRecord
private
def can_admin_runners?
context[:current_user]&.can_admin_all_resources?
end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def batched_owners(runner_assoc_type, assoc_type, key, column_name)
+ BatchLoader::GraphQL.for(runner.id).batch(key: key) do |runner_ids, loader, args|
+ runner_and_owner_ids = runner_assoc_type.where(runner_id: runner_ids).pluck(:runner_id, column_name)
+
+ owner_ids_by_runner_id = runner_and_owner_ids.group_by(&:first).transform_values { |v| v.pluck(1) }
+ owner_ids = runner_and_owner_ids.pluck(1).uniq
+
+ owners = assoc_type.where(id: owner_ids).index_by(&:id)
+
+ runner_ids.each do |runner_id|
+ loader.call(runner_id, owner_ids_by_runner_id[runner_id]&.map { |owner_id| owners[owner_id] } || [])
+ end
+ end
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
end
end
end
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index 00d331df4c3..0f09b1b8996 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -1284,12 +1284,6 @@ module Ci
end
end
- def create_deployment_in_separate_transaction?
- strong_memoize(:create_deployment_in_separate_transaction) do
- ::Feature.enabled?(:create_deployment_in_separate_transaction, project, default_enabled: :yaml)
- end
- end
-
def use_variables_builder_definitions?
strong_memoize(:use_variables_builder_definitions) do
::Feature.enabled?(:ci_use_variables_builder_definitions, project, default_enabled: :yaml)
diff --git a/app/models/container_repository.rb b/app/models/container_repository.rb
index b03d946fc47..4b83eee84fb 100644
--- a/app/models/container_repository.rb
+++ b/app/models/container_repository.rb
@@ -146,6 +146,10 @@ class ContainerRepository < ApplicationRecord
update!(expiration_policy_started_at: Time.zone.now)
end
+ def migration_importing?
+ migration_state == 'importing'
+ end
+
def self.build_from_path(path)
self.new(project: path.repository_project,
name: path.repository_name)
@@ -169,6 +173,11 @@ class ContainerRepository < ApplicationRecord
self.find_by!(project: path.repository_project,
name: path.repository_name)
end
+
+ def self.find_by_path(path)
+ self.find_by(project: path.repository_project,
+ name: path.repository_name)
+ end
end
ContainerRepository.prepend_mod_with('ContainerRepository')
diff --git a/app/models/issue.rb b/app/models/issue.rb
index 0e11e1bb900..8d914b87a9b 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -29,8 +29,10 @@ class Issue < ApplicationRecord
DueDateStruct = Struct.new(:title, :name).freeze
NoDueDate = DueDateStruct.new('No Due Date', '0').freeze
- AnyDueDate = DueDateStruct.new('Any Due Date', '').freeze
+ AnyDueDate = DueDateStruct.new('Any Due Date', 'any').freeze
Overdue = DueDateStruct.new('Overdue', 'overdue').freeze
+ DueToday = DueDateStruct.new('Due Today', 'today').freeze
+ DueTomorrow = DueDateStruct.new('Due Tomorrow', 'tomorrow').freeze
DueThisWeek = DueDateStruct.new('Due This Week', 'week').freeze
DueThisMonth = DueDateStruct.new('Due This Month', 'month').freeze
DueNextMonthAndPreviousTwoWeeks = DueDateStruct.new('Due Next Month And Previous Two Weeks', 'next_month_and_previous_two_weeks').freeze
@@ -107,7 +109,9 @@ class Issue < ApplicationRecord
scope :without_due_date, -> { where(due_date: nil) }
scope :due_before, ->(date) { where('issues.due_date < ?', date) }
scope :due_between, ->(from_date, to_date) { where('issues.due_date >= ?', from_date).where('issues.due_date <= ?', to_date) }
+ scope :due_today, -> { where(due_date: Date.current) }
scope :due_tomorrow, -> { where(due_date: Date.tomorrow) }
+
scope :not_authored_by, ->(user) { where.not(author_id: user) }
scope :order_due_date_asc, -> { reorder(::Gitlab::Database.nulls_last_order('due_date', 'ASC')) }
diff --git a/app/services/auth/container_registry_authentication_service.rb b/app/services/auth/container_registry_authentication_service.rb
index a92a2c8aef5..d72b2abe3b2 100644
--- a/app/services/auth/container_registry_authentication_service.rb
+++ b/app/services/auth/container_registry_authentication_service.rb
@@ -14,6 +14,10 @@ module Auth
:build_destroy_container_image
].freeze
+ FORBIDDEN_IMPORTING_SCOPES = %w[push delete *].freeze
+
+ ActiveImportError = Class.new(StandardError)
+
def execute(authentication_abilities:)
@authentication_abilities = authentication_abilities
@@ -26,12 +30,22 @@ module Auth
end
{ token: authorized_token(*scopes).encoded }
+ rescue ActiveImportError
+ error(
+ 'DENIED',
+ status: 403,
+ message: 'Your repository is currently being migrated to a new platform and writes are temporarily disabled. Go to https://gitlab.com/groups/gitlab-org/-/epics/5523 to learn more.'
+ )
end
def self.full_access_token(*names)
access_token(%w(*), names)
end
+ def self.import_access_token(*names)
+ access_token(%w(import), names)
+ end
+
def self.pull_access_token(*names)
access_token(['pull'], names)
end
@@ -104,6 +118,8 @@ module Auth
def process_repository_access(type, path, actions)
return unless path.valid?
+ raise ActiveImportError if actively_importing?(actions, path)
+
requested_project = path.repository_project
return unless requested_project
@@ -129,6 +145,15 @@ module Auth
}.compact
end
+ def actively_importing?(actions, path)
+ return false if FORBIDDEN_IMPORTING_SCOPES.intersection(actions).empty?
+
+ container_repository = ContainerRepository.find_by_path(path)
+ return false unless container_repository
+
+ container_repository.migration_importing?
+ end
+
def self.migration_eligible(project: nil, repository_path: nil)
return unless Feature.enabled?(:container_registry_migration_phase1)
diff --git a/app/services/ci/retry_build_service.rb b/app/services/ci/retry_build_service.rb
index 7e5d5373648..2371b3615ee 100644
--- a/app/services/ci/retry_build_service.rb
+++ b/app/services/ci/retry_build_service.rb
@@ -40,17 +40,13 @@ module Ci
new_build = clone_build(build)
new_build.run_after_commit do
+ ::Deployments::CreateForBuildService.new.execute(new_build)
+
::MergeRequests::AddTodoWhenBuildFailsService
.new(project: project)
.close(new_build)
end
- if create_deployment_in_separate_transaction?
- new_build.run_after_commit do |new_build|
- ::Deployments::CreateForBuildService.new.execute(new_build)
- end
- end
-
::Ci::Pipelines::AddJobService.new(build.pipeline).execute!(new_build) do |job|
BulkInsertableAssociations.with_bulk_insert do
job.save!
@@ -74,11 +70,7 @@ module Ci
def check_assignable_runners!(build); end
def clone_build(build)
- project.builds.new(build_attributes(build)).tap do |new_build|
- unless create_deployment_in_separate_transaction?
- new_build.assign_attributes(deployment_attributes_for(new_build, build))
- end
- end
+ project.builds.new(build_attributes(build))
end
def build_attributes(build)
@@ -86,7 +78,7 @@ module Ci
[attribute, build.public_send(attribute)] # rubocop:disable GitlabSecurity/PublicSend
end
- if create_deployment_in_separate_transaction? && build.persisted_environment.present?
+ if build.persisted_environment.present?
attributes[:metadata_attributes] ||= {}
attributes[:metadata_attributes][:expanded_environment_name] = build.expanded_environment_name
end
@@ -94,17 +86,6 @@ module Ci
attributes[:user] = current_user
attributes
end
-
- def deployment_attributes_for(new_build, old_build)
- ::Gitlab::Ci::Pipeline::Seed::Build
- .deployment_attributes_for(new_build, old_build.persisted_environment)
- end
-
- def create_deployment_in_separate_transaction?
- strong_memoize(:create_deployment_in_separate_transaction) do
- ::Feature.enabled?(:create_deployment_in_separate_transaction, project, default_enabled: :yaml)
- end
- end
end
end
diff --git a/app/uploaders/import_export_uploader.rb b/app/uploaders/import_export_uploader.rb
index 7b161d72efb..1dcd336d5d9 100644
--- a/app/uploaders/import_export_uploader.rb
+++ b/app/uploaders/import_export_uploader.rb
@@ -12,6 +12,10 @@ class ImportExportUploader < AttachmentUploader
end
def move_to_cache
+ # Exports create temporary files that we can safely move.
+ # Imports may be from project templates that we want to copy.
+ return super if mounted_as == :export_file
+
false
end
diff --git a/app/views/profiles/accounts/_providers.html.haml b/app/views/profiles/accounts/_providers.html.haml
index 73a437a0702..6c6fa32f736 100644
--- a/app/views/profiles/accounts/_providers.html.haml
+++ b/app/views/profiles/accounts/_providers.html.haml
@@ -2,7 +2,7 @@
%label.label-bold
= s_('Profiles|Connected Accounts')
- %p= s_('Profiles|Click on icon to activate signin with one of the following services')
+ %p= s_('Profiles|Select a service to sign in with.')
- providers.each do |provider|
- unlink_allowed = unlink_provider_allowed?(provider)
- link_allowed = link_provider_allowed?(provider)
diff --git a/app/workers/concerns/application_worker.rb b/app/workers/concerns/application_worker.rb
index 83261d9e42e..c1fec4f0196 100644
--- a/app/workers/concerns/application_worker.rb
+++ b/app/workers/concerns/application_worker.rb
@@ -13,7 +13,6 @@ module ApplicationWorker
include Gitlab::SidekiqVersioning::Worker
LOGGING_EXTRA_KEY = 'extra'
- DEFAULT_DELAY_INTERVAL = 1
SAFE_PUSH_BULK_LIMIT = 1000
included do
@@ -92,18 +91,6 @@ module ApplicationWorker
validate_worker_attributes!
end
- def perform_async(*args)
- return super if Gitlab::Database::LoadBalancing.primary_only?
-
- # Worker execution for workers with data_consistency set to :delayed or :sticky
- # will be delayed to give replication enough time to complete
- if utilizes_load_balancing_capabilities? && Feature.disabled?(:skip_scheduling_workers_for_replicas, default_enabled: :yaml)
- perform_in(delay_interval, *args)
- else
- super
- end
- end
-
def set_queue
queue_name = ::Gitlab::SidekiqConfig::WorkerRouter.global.route(self)
sidekiq_options queue: queue_name # rubocop:disable Cop/SidekiqOptionsQueue
@@ -194,12 +181,6 @@ module ApplicationWorker
end
end
- protected
-
- def delay_interval
- DEFAULT_DELAY_INTERVAL.seconds
- end
-
private
def do_push_bulk(args_list)
diff --git a/config/feature_flags/development/create_deployment_in_separate_transaction.yml b/config/feature_flags/development/create_deployment_in_separate_transaction.yml
deleted file mode 100644
index 96cda772beb..00000000000
--- a/config/feature_flags/development/create_deployment_in_separate_transaction.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: create_deployment_in_separate_transaction
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75604
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/346879
-milestone: '14.6'
-type: development
-group: group::release
-default_enabled: true
diff --git a/config/feature_flags/development/skip_scheduling_workers_for_replicas.yml b/config/feature_flags/development/skip_scheduling_workers_for_replicas.yml
deleted file mode 100644
index 494bec1e665..00000000000
--- a/config/feature_flags/development/skip_scheduling_workers_for_replicas.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: skip_scheduling_workers_for_replicas
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/74532
-rollout_issue_url: https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1380
-milestone: '14.5'
-type: development
-group: group::project management
-default_enabled: false
diff --git a/data/removals/14_6/limit_trigger_pipelines.yml b/data/removals/14_6/limit_trigger_pipelines.yml
new file mode 100644
index 00000000000..c69b7feecd2
--- /dev/null
+++ b/data/removals/14_6/limit_trigger_pipelines.yml
@@ -0,0 +1,6 @@
+- name: "Limit the number of triggered pipeline to 25K in free tier"
+ removal_date: Dec 22, 2021 # day the removal was released
+ removal_milestone: "14.6"
+ reporter: dhershkovitch # GitLab username of the person reporting the removal
+ body: |
+ A large amount of triggered pipelines in a single project impacts the performance of GitLab.com. In GitLab 14.6, we are limiting the number of triggered pipelines in a single project on GitLab.com at any given moment to 25,000. This change applies to projects in the free tier only, Premium and Ultimate are not affected by this change.
diff --git a/data/removals/14_6/removal-release-cli-s3.yml b/data/removals/14_6/removal-release-cli-s3.yml
new file mode 100644
index 00000000000..b92d8bb60f8
--- /dev/null
+++ b/data/removals/14_6/removal-release-cli-s3.yml
@@ -0,0 +1,6 @@
+- name: "Release CLI distributed as a generic package"
+ removal_date: Dec 22, 2021 # day the removal was released
+ removal_milestone: "14.6"
+ reporter: kbychu # GitLab username of the person reporting the removal
+ body: |
+ The [release-cli](https://gitlab.com/gitlab-org/release-cli) will be released as a [generic package](https://gitlab.com/gitlab-org/release-cli/-/packages) starting in GitLab 14.2. We will continue to deploy it as a binary to S3 until GitLab 14.5 and stop distributing it in S3 in GitLab 14.6.
diff --git a/doc/administration/postgresql/database_load_balancing.md b/doc/administration/postgresql/database_load_balancing.md
index b83820dd0b6..1324666c32b 100644
--- a/doc/administration/postgresql/database_load_balancing.md
+++ b/doc/administration/postgresql/database_load_balancing.md
@@ -147,9 +147,9 @@ When the list of hosts is updated, it might take a while for the old connections
to be terminated. The `disconnect_timeout` setting can be used to enforce an
upper limit on the time it takes to terminate all old database connections.
-### Handling Stale Reads **(PREMIUM SELF)**
+### Handling stale reads
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3526) in GitLab 10.3.
+> [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/327902) from GitLab Premium to GitLab Free in 14.0.
To prevent reading from an outdated secondary the load balancer checks if it
is in sync with the primary. If the data is recent enough, the
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index 1b884dbfb25..a66503a9cff 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -9030,6 +9030,7 @@ Represents the total number of issues and their weights for a particular day.
| <a id="cirunnermaximumtimeout"></a>`maximumTimeout` | [`Int`](#int) | Maximum timeout (in seconds) for jobs processed by the runner. |
| <a id="cirunnerprivateprojectsminutescostfactor"></a>`privateProjectsMinutesCostFactor` | [`Float`](#float) | Private projects' "minutes cost factor" associated with the runner (GitLab.com only). |
| <a id="cirunnerprojectcount"></a>`projectCount` | [`Int`](#int) | Number of projects that the runner is associated with. |
+| <a id="cirunnerprojects"></a>`projects` | [`ProjectConnection`](#projectconnection) | Projects the runner is associated with. For project runners only. (see [Connections](#connections)) |
| <a id="cirunnerpublicprojectsminutescostfactor"></a>`publicProjectsMinutesCostFactor` | [`Float`](#float) | Public projects' "minutes cost factor" associated with the runner (GitLab.com only). |
| <a id="cirunnerrevision"></a>`revision` | [`String`](#string) | Revision of the runner. |
| <a id="cirunnerrununtagged"></a>`runUntagged` | [`Boolean!`](#boolean) | Indicates the runner is able to run untagged jobs. |
diff --git a/doc/api/issues.md b/doc/api/issues.md
index 5d22952a876..40ae6a3cd8c 100644
--- a/doc/api/issues.md
+++ b/doc/api/issues.md
@@ -29,7 +29,9 @@ When requested across groups or projects, it's expected to be the same as the `f
## List issues
+> The `due_date` property was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/233420) in GitLab 13.3.
> The `weight` property moved to GitLab Premium in 13.9.
+> The `due_date` filters `any`, `today`, and `tomorrow` were [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78460) in GitLab 14.8.
Get all issues the authenticated user has access to. By default it
returns only issues created by the current user. To get all issues,
@@ -61,7 +63,7 @@ GET /issues?state=opened
| `confidential` | boolean | no | Filter confidential or public issues. |
| `created_after` | datetime | no | Return issues created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `created_before` | datetime | no | Return issues created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
-| `due_date` | string | no | Return issues that have no due date, are overdue, or whose due date is this week, this month, or between two weeks ago and next month. Accepts: `0` (no due date), `overdue`, `week`, `month`, `next_month_and_previous_two_weeks`. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/233420) in GitLab 13.3)_ |
+| `due_date` | string | no | Return issues that have no due date, are overdue, or whose due date is this week, this month, or between two weeks ago and next month. Accepts: `0` (no due date), `any`, `today`, `tomorrow`, `overdue`, `week`, `month`, `next_month_and_previous_two_weeks`. |
| `epic_id` **(PREMIUM)** | integer | no | Return issues associated with the given epic ID. `None` returns issues that are not associated with an epic. `Any` returns issues that are associated with an epic. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46887) in GitLab 13.6)_
| `iids[]` | integer array | no | Return only the issues having the given `iid` |
| `in` | string | no | Modify the scope of the `search` attribute. `title`, `description`, or a string joining them with comma. Default is `title,description` |
@@ -231,7 +233,9 @@ Please use `iid` of the `epic` attribute instead.
## List group issues
+> The `due_date` property was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/233420) in GitLab 13.3.
> The `weight` property moved to GitLab Premium in 13.9.
+> The `due_date` filters `any`, `today`, and `tomorrow` were [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78460) in GitLab 14.8.
Get a list of a group's issues.
@@ -264,7 +268,7 @@ GET /groups/:id/issues?state=opened
| `confidential` | boolean | no | Filter confidential or public issues. |
| `created_after` | datetime | no | Return issues created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `created_before` | datetime | no | Return issues created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
-| `due_date` | string | no | Return issues that have no due date, are overdue, or whose due date is this week, this month, or between two weeks ago and next month. Accepts: `0` (no due date), `overdue`, `week`, `month`, `next_month_and_previous_two_weeks`. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/233420) in GitLab 13.3)_ |
+| `due_date` | string | no | Return issues that have no due date, are overdue, or whose due date is this week, this month, or between two weeks ago and next month. Accepts: `0` (no due date), `any`, `today`, `tomorrow`, `overdue`, `week`, `month`, `next_month_and_previous_two_weeks`. |
| `epic_id` **(PREMIUM)** | integer | no | Return issues associated with the given epic ID. `None` returns issues that are not associated with an epic. `Any` returns issues that are associated with an epic. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46887) in GitLab 13.6)_
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) owned by the authenticated user |
| `iids[]` | integer array | no | Return only the issues having the given `iid` |
@@ -431,7 +435,9 @@ Please use `iid` of the `epic` attribute instead.
## List project issues
+> The `due_date` property was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/233420) in GitLab 13.3.
> The `weight` property moved to GitLab Premium in 13.9.
+> The `due_date` filters `any`, `today`, and `tomorrow` were [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78460) in GitLab 14.8.
Get a list of a project's issues.
@@ -464,7 +470,7 @@ GET /projects/:id/issues?state=opened
| `confidential` | boolean | no | Filter confidential or public issues. |
| `created_after` | datetime | no | Return issues created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `created_before` | datetime | no | Return issues created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
-| `due_date` | string | no | Return issues that have no due date, are overdue, or whose due date is this week, this month, or between two weeks ago and next month. Accepts: `0` (no due date), `overdue`, `week`, `month`, `next_month_and_previous_two_weeks`. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/233420) in GitLab 13.3)_ |
+| `due_date` | string | no | Return issues that have no due date, are overdue, or whose due date is this week, this month, or between two weeks ago and next month. Accepts: `0` (no due date), `any`, `today`, `tomorrow`, `overdue`, `week`, `month`, `next_month_and_previous_two_weeks`. |
| `epic_id` **(PREMIUM)** | integer | no | Return issues associated with the given epic ID. `None` returns issues that are not associated with an epic. `Any` returns issues that are associated with an epic. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46887) in GitLab 13.6)_
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
| `iids[]` | integer array | no | Return only the issues having the given `iid` |
diff --git a/doc/ci/yaml/script.md b/doc/ci/yaml/script.md
index ca1e79c2395..4bffcbca1cc 100644
--- a/doc/ci/yaml/script.md
+++ b/doc/ci/yaml/script.md
@@ -4,7 +4,7 @@ group: Pipeline Authoring
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
---
-# GitLab CI/CD script syntax **(FREE)**
+# Format scripts and job logs **(FREE)**
You can use special syntax in [`script`](index.md#script) sections to:
diff --git a/doc/development/database/dbcheck-migrations-job.md b/doc/development/database/dbcheck-migrations-job.md
new file mode 100644
index 00000000000..af72e28a875
--- /dev/null
+++ b/doc/development/database/dbcheck-migrations-job.md
@@ -0,0 +1,67 @@
+---
+stage: Enablement
+group: Database
+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
+---
+
+# db:check-migrations job
+
+This job runs on the test stage of a merge request pipeline. It checks:
+
+1. A schema dump comparison between the author's working branch and the target branch,
+ after executing a rollback of your new migrations. This check validates that the
+ schema properly resets to what it was before executing this new migration.
+1. A schema dump comparison between the author's working branch and the `db/structure.sql`
+ file that the author committed. This check validates that it contains all the expected changes
+ in the migration.
+1. A Git diff between the `db/schema_migrations` that the author committed and the
+ one that the script generated after running migrations. This check validates that everything
+ was properly committed.
+
+## Troubleshooting
+
+### False positives
+
+This job is allowed to fail, because it can throw some false positives.
+
+For example, when we drop a column and then roll back, this column is always
+re-added at the end of the list of columns. If the column was previously in
+the middle of the list, the rollback can't return the schema back exactly to
+its previous state. The job fails, but it's an acceptable situation.
+
+For a real-life example, refer to
+[this failed job](https://gitlab.com/gitlab-org/gitlab/-/jobs/2006544972#L138).
+Here, the author dropped the `position` column.
+
+### Schema dump comparison fails after rollback
+
+This failure often happens if your working branch is behind the target branch.
+A real scenario:
+
+```mermaid
+graph LR
+ Main((main<br>commit A)) ===> |remove constraint<br>fk_rails_dbebdaa8fe| MainB((main<br>commit B))
+ Main((main<br>commit A)) --> |checkout<br>dev| DevA((dev<br>commit A)):::dev
+ DevA((dev<br>commit A)) --> |add column<br>dependency_proxy_size| DevC((dev<br>commit C)):::dev
+ DevC -.-> |CI pipeline<br>executes| JOB-FAILED((JOB FAILED!)):::error
+
+ classDef main fill:#f4f0ff,stroke:#7b58cf
+ classDef dev fill:#e9f3fc,stroke:#1f75cb
+ classDef error fill:#f15146,stroke:#d4121a
+```
+
+1. You check out the `dev` working branch from the `main` target branch. At this point,
+ each branch has their `HEAD` at commit A.
+1. Someone works on the `main` branch and drops the `fk_rails_dbebdaa8fe` constraint,
+ thus creating commit B on `main`.
+1. You add column `dependency_proxy_size` to your `dev` branch.
+1. The `db:check-migrations` job fails for your `dev` branch's CI/CD pipeline, because
+ the `structure.sql` file did not rollback to its expected state.
+
+This happened because branch `dev` contained commits A and C, not B. Its database schema
+did not know about the removal of the `fk_rails_dbebdaa8fe` constraint. When comparing the two
+schemas, the `dev` branch contained this constraint while the `main` branch didn't.
+
+This example really happened. Read the [job failure logs](https://gitlab.com/gitlab-org/gitlab/-/jobs/1992050890).
+
+To fix these kind of issues, rebase the working branch onto the target branch to get the latest changes.
diff --git a/doc/development/database/index.md b/doc/development/database/index.md
index a7b752e14ef..efc48f72d00 100644
--- a/doc/development/database/index.md
+++ b/doc/development/database/index.md
@@ -19,6 +19,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
- [Understanding EXPLAIN plans](../understanding_explain_plans.md)
- [explain.depesz.com](https://explain.depesz.com/) or [explain.dalibo.com](https://explain.dalibo.com/) for visualizing the output of `EXPLAIN`
- [pgFormatter](https://sqlformat.darold.net/) a PostgreSQL SQL syntax beautifier
+- [db:check-migrations job](dbcheck-migrations-job.md)
## Migrations
diff --git a/doc/development/database_review.md b/doc/development/database_review.md
index 082c843a12c..f968865114b 100644
--- a/doc/development/database_review.md
+++ b/doc/development/database_review.md
@@ -49,7 +49,7 @@ If new migrations are introduced, in the MR **you are required to provide**:
Note that we have automated tooling for
[GitLab](https://gitlab.com/gitlab-org/gitlab) (provided by the
-`db:check-migrations` pipeline job) that provides this output for migrations on
+[`db:check-migrations`](database/dbcheck-migrations-job.md) pipeline job) that provides this output for migrations on
~database merge requests. You do not need to provide this information manually
if the bot can do it for you. The bot also checks that migrations are correctly
reversible.
diff --git a/doc/subscriptions/bronze_starter.md b/doc/subscriptions/bronze_starter.md
index 2c66d32f669..78ac39395af 100644
--- a/doc/subscriptions/bronze_starter.md
+++ b/doc/subscriptions/bronze_starter.md
@@ -17,9 +17,7 @@ the tiers are no longer mentioned in GitLab documentation:
- [Activate GitLab EE with a license](../user/admin_area/license.md)
- [Add a help message to the sign-in page](../user/admin_area/settings/help_page.md#add-a-help-message-to-the-sign-in-page)
-- [Burndown and burnup charts](../user/project/milestones/burndown_and_burnup_charts.md),
- including [per-project charts](../user/project/milestones/index.md#project-burndown-charts) and
- [per-group charts](../user/project/milestones/index.md#group-burndown-charts)
+- [Burndown and burnup charts](../user/project/milestones/burndown_and_burnup_charts.md) in the [Milestone View](../user/project/milestones/index.md#burndown-charts),
- [Code owners](../user/project/code_owners.md)
- Description templates:
- [Setting a default template for merge requests and issues](../user/project/description_templates.md#set-a-default-template-for-merge-requests-and-issues)
diff --git a/doc/update/removals.md b/doc/update/removals.md
index 94ce815a110..ef5fcd76f80 100644
--- a/doc/update/removals.md
+++ b/doc/update/removals.md
@@ -388,3 +388,13 @@ In GitLab 14.3, we will remove the ability to filter by `name` in the [list proj
The support for [`gitlab_pages['use_legacy_storage']` setting](https://docs.gitlab.com/ee/administration/pages/index.html#domain-source-configuration-before-140) in Omnibus installations has been removed.
In 14.0 we removed [`domain_config_source`](https://docs.gitlab.com/ee/administration/pages/index.html#domain-source-configuration-before-140) which had been previously deprecated, and allowed users to specify disk storage. In 14.0 we added `use_legacy_storage` as a **temporary** flag to unblock upgrades, and allow us to debug issues with our users and it was deprecated and communicated for removal in 14.3.
+
+## 14.6
+
+### Limit the number of triggered pipeline to 25K in free tier
+
+A large amount of triggered pipelines in a single project impacts the performance of GitLab.com. In GitLab 14.6, we are limiting the number of triggered pipelines in a single project on GitLab.com at any given moment to 25,000. This change applies to projects in the free tier only, Premium and Ultimate are not affected by this change.
+
+### Release CLI distributed as a generic package
+
+The [release-cli](https://gitlab.com/gitlab-org/release-cli) will be released as a [generic package](https://gitlab.com/gitlab-org/release-cli/-/packages) starting in GitLab 14.2. We will continue to deploy it as a binary to S3 until GitLab 14.5 and stop distributing it in S3 in GitLab 14.6.
diff --git a/doc/user/application_security/policies/img/scan_result_policy_yaml_mode_v14_6.png b/doc/user/application_security/policies/img/scan_result_policy_yaml_mode_v14_6.png
new file mode 100644
index 00000000000..57649c58d8b
--- /dev/null
+++ b/doc/user/application_security/policies/img/scan_result_policy_yaml_mode_v14_6.png
Binary files differ
diff --git a/doc/user/application_security/policies/index.md b/doc/user/application_security/policies/index.md
index 11f2b91177a..ce6f08483a6 100644
--- a/doc/user/application_security/policies/index.md
+++ b/doc/user/application_security/policies/index.md
@@ -211,6 +211,46 @@ scan_execution_policy:
- scan: dast
scanner_profile: Scanner Profile C
site_profile: Site Profile D
+scan_result_policy:
+- name: critical vulnerability CS approvals
+ description: critical severity level only for container scanning
+ enabled: true
+ rules:
+ - type: scan_finding
+ branches:
+ - main
+ scanners:
+ - container_scanning
+ vulnerabilities_allowed: 1
+ severity_levels:
+ - critical
+ vulnerability_states:
+ - newly_detected
+ actions:
+ - type: require_approval
+ approvals_required: 1
+ user_approvers:
+ - adalberto.dare
+- name: secondary CS approvals
+ description: secondary only for container scanning
+ enabled: true
+ rules:
+ - type: scan_finding
+ branches:
+ - main
+ scanners:
+ - container_scanning
+ vulnerabilities_allowed: 1
+ severity_levels:
+ - low
+ - unknown
+ vulnerability_states:
+ - newly_detected
+ actions:
+ - type: require_approval
+ approvals_required: 1
+ user_approvers:
+ - sam.white
```
## Security Policy project selection
@@ -445,6 +485,166 @@ actions:
- scan: container_scanning
```
+### Scan Result Policy editor
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/77814) in GitLab 14.8 with a flag named `scan_result_policy`. Disabled by default.
+
+NOTE:
+Only project Owners have the [permissions](../../permissions.md#project-members-permissions)
+to select Security Policy Project.
+
+Once your policy is complete, save it by selecting **Create merge request** at the bottom of the
+editor. This redirects you to the merge request on the project's configured security policy project.
+If a security policy project doesn't link to your project, GitLab creates such a project for you.
+Existing policies can also be removed from the editor interface by selecting **Delete policy** at
+the bottom of the editor.
+
+The policy editor only supports YAML mode. To follow work on Rule mode, see the epic
+[Allow Users to Edit Rule-mode Scan Result Policies in the Policy UI](https://gitlab.com/groups/gitlab-org/-/epics/5363).
+
+![Scan Result Policy Editor YAML Mode](img/scan_result_policy_yaml_mode_v14_6.png)
+
+### Scan Result Policies schema
+
+The YAML file with Scan Result Policies consists of an array of objects matching the Scan Result
+Policy schema nested under the `scan_result_policy` key. You can configure a maximum of five
+policies under the `scan_result_policy` key.
+
+When you save a new policy, GitLab validates its contents against [this JSON schema](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/validators/json_schemas/security_orchestration_policy.json).
+If you're not familiar with how to read [JSON schemas](https://json-schema.org/),
+the following sections and tables provide an alternative.
+
+| Field | Type | Possible values | Description |
+|-------|------|-----------------|-------------|
+| `scan_result_policy` | `array` of Scan Result Policy | | List of Scan Result Policies (maximum 5). |
+
+### Scan Result Policy schema
+
+| Field | Type | Possible values | Description |
+|-------|------|-----------------|-------------|
+| `name` | `string` | | Name of the policy. |
+| `description` (optional) | `string` | | Description of the policy. |
+| `enabled` | `boolean` | `true`, `false` | Flag to enable (`true`) or disable (`false`) the policy. |
+| `rules` | `array` of rules | | List of rules that the policy applies. |
+| `actions` | `array` of actions | | List of actions that the policy enforces. |
+
+### `scan_finding` rule type
+
+This rule enforces the defined actions based on the information provided.
+
+| Field | Type | Possible values | Description |
+|------------|------|-----------------|-------------|
+| `type` | `string` | `scan_finding` | The rule's type. |
+| `branches` | `array` of `string` | `*` or the branch's name | The branch the given policy applies to (supports wildcard). |
+| `scanners` | `array` of `string` | `sast`, `secret_detection`, `dependency_scanning`, `container_scanning`, `dast`, `coverage_fuzzing`, `api_fuzzing` | The security scanners for this rule to consider. |
+| `vulnerabilities_allowed` | `integer` | Greater than or equal to zero | Number of vulnerabilities allowed before this rule is considered. |
+| `severity_levels` | `array` of `string` | `info`, `unknown`, `low`, `medium`, `high`, `critical`| The severity levels for this rule to consider. |
+| `vulnerability_states` | `array` of `string` | `newly_detected`, `detected`, `confirmed`, `resolved`, `dismissed` | The vulnerability states for this rule to consider when the target branch is set to the default branch. |
+
+### `require_approval` action type
+
+This action sets an approval rule to be required when conditions are met for at least one rule in
+the defined policy.
+
+| Field | Type | Possible values | Description |
+|-------|------|-----------------|-------------|
+| `type` | `string` | `require_approval` | The action's type. |
+| `approvals_required` | `integer` | Greater than or equal to zero | The number of MR approvals required. |
+| `user_approvers` | `array` of `string` | Username of one of more users | The users to consider as approvers. |
+| `user_approvers_ids` | `array` of `integer` | ID of one of more users | The IDs of users to consider as approvers. |
+| `group_approvers` | `array` of `string` | Path of one of more groups | The groups to consider as approvers. |
+| `group_approvers_ids` | `array` of `integer` | ID of one of more groups | The IDs of groups to consider as approvers. |
+
+Requirements and limitations:
+
+- You must add the respective [security scanning tools](../index.md#security-scanning-tools).
+ Otherwise, Scan Result Policies won't have any effect.
+- The maximum number of policies is five.
+- Each policy can have a maximum of five rules.
+
+### Example security scan result policies project
+
+You can use this example in a `.gitlab/security-policies/policy.yml`, as described in
+[Security policies project](#security-policies-project):
+
+```yaml
+---
+scan_result_policy:
+- name: critical vulnerability CS approvals
+ description: critical severity level only for container scanning
+ enabled: true
+ rules:
+ - type: scan_finding
+ branches:
+ - main
+ scanners:
+ - container_scanning
+ vulnerabilities_allowed: 0
+ severity_levels:
+ - critical
+ vulnerability_states:
+ - newly_detected
+ actions:
+ - type: require_approval
+ approvals_required: 1
+ user_approvers:
+ - adalberto.dare
+- name: secondary CS approvals
+ description: secondary only for container scanning
+ enabled: true
+ rules:
+ - type: scan_finding
+ branches:
+ - main
+ scanners:
+ - container_scanning
+ vulnerabilities_allowed: 1
+ severity_levels:
+ - low
+ - unknown
+ vulnerability_states:
+ - newly_detected
+ actions:
+ - type: require_approval
+ approvals_required: 1
+ user_approvers:
+ - sam.white
+```
+
+In this example:
+
+- Every MR that contains new `critical` vulnerabilities identified by container scanning requires
+ one approval from `alberto.dare`.
+- Every MR that contains more than one new `low` or `unknown` vulnerability identified by container
+ scanning requires one approval from `sam.white`.
+
+### Example for Scan Result Policy editor
+
+You can use this example in the YAML mode of the [Scan Result Policy editor](#scan-result-policy-editor).
+It corresponds to a single object from the previous example:
+
+```yaml
+- name: critical vulnerability CS approvals
+ description: critical severity level only for container scanning
+ enabled: true
+ rules:
+ - type: scan_finding
+ branches:
+ - main
+ scanners:
+ - container_scanning
+ vulnerabilities_allowed: 1
+ severity_levels:
+ - critical
+ vulnerability_states:
+ - newly_detected
+ actions:
+ - type: require_approval
+ approvals_required: 1
+ user_approvers:
+ - adalberto.dare
+```
+
## Roadmap
See the [Category Direction page](https://about.gitlab.com/direction/protect/container_network_security/)
diff --git a/doc/user/profile/account/delete_account.md b/doc/user/profile/account/delete_account.md
index 365f96b48b3..6b3e3a7d268 100644
--- a/doc/user/profile/account/delete_account.md
+++ b/doc/user/profile/account/delete_account.md
@@ -55,13 +55,14 @@ There are two options for deleting users:
- **Delete user and contributions**
When using the **Delete user** option, not all associated records are deleted with the user.
-Here's a list of things that are **not** deleted:
-
-- Issues that the user created.
-- Merge requests that the user created.
-- Notes that the user created.
-- Abuse reports that the user reported.
-- Award emoji that the user created.
+Here's a list of things created by the user that are **not** deleted:
+
+- Abuse reports
+- Award emoji
+- Epics
+- Issues
+- Merge requests
+- Notes
Instead of being deleted, these records are moved to a system-wide
user with the username "Ghost User", whose sole purpose is to act as a container
diff --git a/doc/user/project/clusters/kubernetes_pod_logs.md b/doc/user/project/clusters/kubernetes_pod_logs.md
index 19166a1ff8c..b3baac02d74 100644
--- a/doc/user/project/clusters/kubernetes_pod_logs.md
+++ b/doc/user/project/clusters/kubernetes_pod_logs.md
@@ -6,8 +6,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Kubernetes Logs (DEPRECATED) **(FREE)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/4752) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.0.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26383) to [GitLab Free](https://about.gitlab.com/pricing/) 12.9.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/4752) in GitLab 11.0.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26383) from GitLab Ultimate to GitLab Free 12.9.
> - [Deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
WARNING:
diff --git a/doc/user/project/issue_board.md b/doc/user/project/issue_board.md
index 47a2d215024..bbd2a608d2c 100644
--- a/doc/user/project/issue_board.md
+++ b/doc/user/project/issue_board.md
@@ -496,6 +496,9 @@ The steps depend on the scope of the list:
### Filter issues
+> - Filtering by iteration [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118742) in GitLab 13.6.
+> - Filtering by issue type [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/268152) in GitLab 14.6.
+
You can use the filters on top of your issue board to show only
the results you want. It's similar to the filtering used in the [issue tracker](issues/index.md).
@@ -504,11 +507,12 @@ You can filter by the following:
- Assignee
- Author
- Epic
-- Iteration ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118742) in GitLab 13.6)
+- Iteration
- Label
- Milestone
- My Reaction
- Release
+- Type (issue/incident)
- Weight
#### Filtering issues in a group board
diff --git a/doc/user/project/issues/csv_export.md b/doc/user/project/issues/csv_export.md
index a9fca4f2b75..947fbdcc2d1 100644
--- a/doc/user/project/issues/csv_export.md
+++ b/doc/user/project/issues/csv_export.md
@@ -61,29 +61,29 @@ fields if needed, and newlines to separate rows. The first row contains the
headers, which are listed in the following table along with a description of
the values:
-| Column | Description |
-|-------------------|-------------|
-| Issue ID | Issue `iid` |
-| URL | A link to the issue on GitLab |
-| Title | Issue `title` |
-| State | `Open` or `Closed` |
-| Description | Issue `description` |
-| Author | Full name of the issue author |
-| Author Username | Username of the author, with the `@` symbol omitted |
-| Assignee | Full name of the issue assignee |
-| Assignee Username | Username of the author, with the `@` symbol omitted |
-| Confidential | `Yes` or `No` |
-| Locked | `Yes` or `No` |
-| Due Date | Formatted as `YYYY-MM-DD` |
-| Created At (UTC) | Formatted as `YYYY-MM-DD HH:MM:SS` |
-| Updated At (UTC) | Formatted as `YYYY-MM-DD HH:MM:SS` |
-| Milestone | Title of the issue milestone |
-| Weight | Issue weight |
-| Labels | Title of any labels joined with a `,` |
-| Time Estimate | [Time estimate](../time_tracking.md#estimates) in seconds |
-| Time Spent | [Time spent](../time_tracking.md#time-spent) in seconds |
-| Epic ID | ID of the parent epic **(ULTIMATE)**, introduced in 12.7 |
-| Epic Title | Title of the parent epic **(ULTIMATE)**, introduced in 12.7 |
+| Column | Description |
+|------------------------------------------|-----------------------------------------------------------|
+| Issue ID | Issue `iid` |
+| URL | A link to the issue on GitLab |
+| Title | Issue `title` |
+| State | `Open` or `Closed` |
+| Description | Issue `description` |
+| Author | Full name of the issue author |
+| Author Username | Username of the author, with the `@` symbol omitted |
+| Assignee | Full name of the issue assignee |
+| Assignee Username | Username of the author, with the `@` symbol omitted |
+| Confidential | `Yes` or `No` |
+| Locked | `Yes` or `No` |
+| Due Date | Formatted as `YYYY-MM-DD` |
+| Created At (UTC) | Formatted as `YYYY-MM-DD HH:MM:SS` |
+| Updated At (UTC) | Formatted as `YYYY-MM-DD HH:MM:SS` |
+| Milestone | Title of the issue milestone |
+| Weight | Issue weight |
+| Labels | Title of any labels joined with a `,` |
+| Time Estimate | [Time estimate](../time_tracking.md#estimates) in seconds |
+| Time Spent | [Time spent](../time_tracking.md#time-spent) in seconds |
+| [Epic](../../group/epics/index.md) ID | ID of the parent epic, introduced in 12.7 |
+| [Epic](../../group/epics/index.md) Title | Title of the parent epic, introduced in 12.7 |
## Limitations
diff --git a/doc/user/project/issues/design_management.md b/doc/user/project/issues/design_management.md
index ecf35fc4dcf..e7bb5ad4eeb 100644
--- a/doc/user/project/issues/design_management.md
+++ b/doc/user/project/issues/design_management.md
@@ -6,9 +6,9 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Design Management **(FREE)**
-> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/660) in GitLab Premium 12.2.
-> - Support for SVGs [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12771) in GitLab Premium 12.4.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212566) to GitLab Free in 13.0.
+> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/660) in GitLab 12.2.
+> - Support for SVGs [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12771) in GitLab 12.4.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212566) from GitLab Premium to GitLab Free in 13.0.
Design Management allows you to upload design assets (including wireframes and mockups)
to GitLab issues and keep them stored in a single place, accessed by the Design
@@ -84,10 +84,10 @@ You can find to the **Design Management** section in the issue description:
## Adding designs
-> - Drag and drop uploads [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/34353) in GitLab Premium 12.9.
-> - New version creation on upload [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/34353) in GitLab Premium 12.9.
+> - Drag and drop uploads [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/34353) in GitLab 12.9.
+> - New version creation on upload [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/34353) in GitLab 12.9.
> - Copy and paste uploads [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/202634) in GitLab 12.10.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212566) to GitLab Free in 13.0.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212566) from GitLab Premium to GitLab Free in 13.0.
To upload Design images, drag files from your computer and drop them in the Design Management section,
or select **click to upload** to select images from your file browser:
@@ -142,9 +142,9 @@ to help summarize changes between versions.
### Exploring designs by zooming
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13217) in GitLab Premium 12.7.
-> - Drag to move a zoomed image [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/197324) in GitLab 12.10.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212566) to GitLab Free in 13.0.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13217) in GitLab 12.7.
+> - Ability to drag a zoomed image to move it [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/197324) in GitLab 12.10.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212566) from GitLab Premium to GitLab Free in 13.0.
Designs can be explored in greater detail by zooming in and out of the image.
Control the amount of zoom with the `+` and `-` buttons at the bottom of the image.
@@ -155,8 +155,8 @@ While zoomed in, you can drag the image to move around it.
## Deleting designs
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11089) in GitLab Premium 12.4.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212566) to GitLab Free in 13.0.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11089) in GitLab 12.4.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212566) from GitLab Premium to GitLab Free in 13.0.
There are two ways to delete designs: manually delete them
individually, or select a few of them to delete at once,
@@ -190,8 +190,8 @@ You can change the order of designs by dragging them to a new position.
## Starting discussions on designs
-> - Adjusting a pin's position [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/34353) in GitLab Premium 12.8.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212566) to GitLab Free in 13.0.
+> - Adjusting a pin's position [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/34353) adjusting a pin's position in GitLab 12.8.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212566) from GitLab Premium to GitLab Free in 13.0.
When a design is uploaded, you can start a discussion by selecting
the image on the exact location you would like the discussion to be focused on.
diff --git a/doc/user/project/merge_requests/test_coverage_visualization.md b/doc/user/project/merge_requests/test_coverage_visualization.md
index 1f84964c619..6a0893ec9d7 100644
--- a/doc/user/project/merge_requests/test_coverage_visualization.md
+++ b/doc/user/project/merge_requests/test_coverage_visualization.md
@@ -40,6 +40,7 @@ Other coverage analysis frameworks support the format out of the box, for exampl
- [Istanbul](https://istanbul.js.org/docs/advanced/alternative-reporters/#cobertura) (JavaScript)
- [Coverage.py](https://coverage.readthedocs.io/en/coverage-5.0.4/cmd.html#xml-reporting) (Python)
+- [PHPUnit](https://github.com/sebastianbergmann/phpunit-documentation-english/blob/master/src/textui.rst#command-line-options) (PHP)
Once configured, if you create a merge request that triggers a pipeline which collects
coverage reports, the coverage is shown in the diff view. This includes reports
@@ -236,7 +237,7 @@ run tests:
image: python:3
script:
- pip install pytest pytest-cov
- - coverage run -m pytest
+ - coverage run -m pytest
- coverage report
- coverage xml
artifacts:
@@ -244,6 +245,42 @@ run tests:
cobertura: coverage.xml
```
+### PHP example
+
+The following [`.gitlab-ci.yml`](../../../ci/yaml/index.md) example for PHP uses [PHPUnit](https://phpunit.readthedocs.io/)
+to collect test coverage data and generate the report.
+
+With a minimal [`phpunit.xml`](https://phpunit.readthedocs.io/en/9.5/configuration.html) file (you may reference
+[this example repository](https://gitlab.com/yookoala/code-coverage-visualization-with-php/)), you can run the test and
+generate the coverage xml:
+
+```yaml
+run tests:
+ stage: test
+ image: php:latest
+ variables:
+ XDEBUG_MODE: coverage
+ before_script:
+ - apt-get update && apt-get -yq install git unzip zip libzip-dev zlib1g-dev
+ - docker-php-ext-install zip
+ - pecl install xdebug && docker-php-ext-enable xdebug
+ - php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
+ - php composer-setup.php --install-dir=/usr/local/bin --filename=composer
+ - composer install
+ - composer require --dev phpunit/phpunit phpunit/php-code-coverage
+ script:
+ - php ./vendor/bin/phpunit --coverage-text --coverage-cobertura=coverage.cobertura.xml
+ artifacts:
+ reports:
+ cobertura: coverage.cobertura.xml
+```
+
+[Codeception](https://codeception.com/), through PHPUnit, also supports generating Cobertura report with
+[`run`](https://codeception.com/docs/reference/Commands#run). The path for the generated file
+depends on the `--coverage-cobertura` option and [`paths`](https://codeception.com/docs/reference/Configuration#paths)
+configuration for the [unit test suite](https://codeception.com/docs/05-UnitTests). Configure `.gitlab-ci.yml`
+to find Cobertura in the appropriate path.
+
### C/C++ example
The following [`.gitlab-ci.yml`](../../../ci/yaml/index.md) example for C/C++ with
@@ -272,3 +309,35 @@ run tests:
reports:
cobertura: build/coverage.xml
```
+
+### Go example
+
+The following [`.gitlab-ci.yml`](../../../ci/yaml/index.md) example for Go uses:
+
+- [`go test`](https://go.dev/doc/tutorial/add-a-test) to run tests.
+- [`gocover-cobertura`](https://github.com/t-yuki/gocover-cobertura) to convert Go's coverage profile into the Cobertura XML format.
+
+This example assumes that [Go modules](https://go.dev/ref/mod) are being used.
+Using Go modules causes paths within the coverage profile to be prefixed with your
+project's module identifier, which can be found in the `go.mod` file. This
+prefix must be removed for GitLab to parse the Cobertura XML file correctly. You can use the following `sed` command to remove the prefix:
+
+```shell
+sed -i 's;filename=\"<YOUR_MODULE_ID>/;filename=\";g' coverage.xml
+```
+
+Replace the `gitlab.com/my-group/my-project` placeholder in the following example with your own module identifier to make it work.
+
+```yaml
+run tests:
+ stage: test
+ image: golang:1.17
+ script:
+ - go install
+ - go test . -coverprofile=coverage.txt -covermode count
+ - go run github.com/t-yuki/gocover-cobertura < coverage.txt > coverage.xml
+ - sed -i 's;filename=\"gitlab.com/my-group/my-project/;filename=\";g' coverage.xml
+ artifacts:
+ reports:
+ cobertura: coverage.xml
+```
diff --git a/doc/user/project/milestones/burndown_and_burnup_charts.md b/doc/user/project/milestones/burndown_and_burnup_charts.md
index 7c22b271ec2..c6becc59ddc 100644
--- a/doc/user/project/milestones/burndown_and_burnup_charts.md
+++ b/doc/user/project/milestones/burndown_and_burnup_charts.md
@@ -11,7 +11,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
![burndown and burnup chart](img/burndown_and_burnup_charts_v13_6.png)
-## Burndown charts **(PREMIUM)**
+## Burndown charts
> - [Added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6495) to GitLab 11.2 for group milestones.
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/6903) [fixed burndown charts](#fixed-burndown-charts) in GitLab 13.6.
@@ -100,7 +100,7 @@ Therefore, when the milestone start date is changed, the number of opened issues
change.
Reopened issues are considered as having been opened on the day after they were last closed.
-## Burnup charts **(PREMIUM)**
+## Burnup charts
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/6903) in GitLab 13.6.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/268350) in GitLab 13.7.
diff --git a/doc/user/project/milestones/img/milestones_new_group_milestone_v13_5.png b/doc/user/project/milestones/img/milestones_new_group_milestone_v13_5.png
deleted file mode 100644
index ffe1328b7d3..00000000000
--- a/doc/user/project/milestones/img/milestones_new_group_milestone_v13_5.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/milestones/index.md b/doc/user/project/milestones/index.md
index fb61e123faf..4e6b516d64c 100644
--- a/doc/user/project/milestones/index.md
+++ b/doc/user/project/milestones/index.md
@@ -56,27 +56,17 @@ If you're in a project and select **Issues > Milestones**, GitLab displays only
NOTE:
A permission level of [Developer or higher](../../permissions.md) is required to create milestones.
-### New project milestone
+Milestones can be created either at project or group level.
-To create a project milestone:
+To create a milestone:
-1. In a project, go to **{issues}** **Issues > Milestones**.
+1. On the top bar, select **Menu > Projects** and find your project or **Menu > Groups** and find your group.
+1. On the left sidebar, select **Issues > Milestones**.
1. Select **New milestone**.
1. Enter the title, an optional description, an optional start date, and an optional due date.
1. Select **New milestone**.
-![New project milestone](img/milestones_new_project_milestone.png)
-
-### New group milestone
-
-To create a group milestone:
-
-1. In a group, go to **{issues}** **Issues > Milestones**.
-1. Select **New milestone**.
-1. Enter the title, an optional description, an optional start date, and an optional due date.
-1. Select **New milestone**.
-
-![New group milestone](img/milestones_new_group_milestone_v13_5.png)
+![New milestone](img/milestones_new_project_milestone.png)
## Editing milestones
@@ -155,24 +145,19 @@ There are also tabs below these that show the following:
- Completed Issues (closed)
- **Merge Requests**: Shows all merge requests assigned to the milestone. These are displayed in four columns named:
- Work in progress (open and unassigned)
- - Waiting for merge (open and unassigned)
+ - Waiting for merge (open and assigned)
- Rejected (closed)
- Merged
- **Participants**: Shows all assignees of issues assigned to the milestone.
- **Labels**: Shows all labels that are used in issues assigned to the milestone.
-### Project Burndown Charts
+### Burndown Charts
-For project milestones, a [burndown chart](burndown_and_burnup_charts.md) is in the milestone view,
+The milestone view contains a [burndown chart](burndown_and_burnup_charts.md),
showing the progress of completing a milestone.
![burndown chart](img/burndown_chart_v13_6.png)
-### Group Burndown Charts
-
-For group milestones, a [burndown chart](burndown_and_burnup_charts.md) is in the milestone view,
-showing the progress of completing a milestone.
-
### Milestone sidebar
The milestone sidebar on the milestone view shows the following:
diff --git a/lib/api/issues.rb b/lib/api/issues.rb
index 46124a74e9d..a5d6a6d7cf3 100644
--- a/lib/api/issues.rb
+++ b/lib/api/issues.rb
@@ -80,7 +80,7 @@ module API
desc: 'Return issues ordered by `created_at`, `due_date`, `label_priority`, `milestone_due`, `popularity`, `priority`, `relative_position`, `title`, or `updated_at` fields.'
optional :sort, type: String, values: %w[asc desc], default: 'desc',
desc: 'Return issues sorted in `asc` or `desc` order.'
- optional :due_date, type: String, values: %w[0 overdue week month next_month_and_previous_two_weeks] << '',
+ optional :due_date, type: String, values: %w[0 any today tomorrow overdue week month next_month_and_previous_two_weeks] << '',
desc: 'Return issues that have no due date (`0`), or whose due date is this week, this month, between two weeks ago and next month, or which are overdue. Accepts: `overdue`, `week`, `month`, `next_month_and_previous_two_weeks`, `0`'
optional :issue_type, type: String, values: WorkItems::Type.allowed_types_for_issues, desc: "The type of the issue. Accepts: #{WorkItems::Type.allowed_types_for_issues.join(', ')}"
diff --git a/lib/bitbucket_server/representation/repo.rb b/lib/bitbucket_server/representation/repo.rb
index dab7f8f22a1..4cd5b75bbed 100644
--- a/lib/bitbucket_server/representation/repo.rb
+++ b/lib/bitbucket_server/representation/repo.rb
@@ -30,7 +30,7 @@ module BitbucketServer
end
def description
- project['description']
+ raw['description']
end
def full_name
diff --git a/lib/gitlab/ci/pipeline/chain/build.rb b/lib/gitlab/ci/pipeline/chain/build.rb
index bbdc6b65b96..6feb693221b 100644
--- a/lib/gitlab/ci/pipeline/chain/build.rb
+++ b/lib/gitlab/ci/pipeline/chain/build.rb
@@ -21,10 +21,6 @@ module Gitlab
merge_request: @command.merge_request,
external_pull_request: @command.external_pull_request,
locked: @command.project.default_pipeline_lock)
-
- # Initialize the feature flag at the beginning of the pipeline creation process
- # so that the flag references in the latter chains return the same value.
- @pipeline.create_deployment_in_separate_transaction?
end
def break?
diff --git a/lib/gitlab/ci/pipeline/chain/create_deployments.rb b/lib/gitlab/ci/pipeline/chain/create_deployments.rb
index b913ba3c87d..a8276d84b87 100644
--- a/lib/gitlab/ci/pipeline/chain/create_deployments.rb
+++ b/lib/gitlab/ci/pipeline/chain/create_deployments.rb
@@ -6,8 +6,6 @@ module Gitlab
module Chain
class CreateDeployments < Chain::Base
def perform!
- return unless pipeline.create_deployment_in_separate_transaction?
-
create_deployments!
end
diff --git a/lib/gitlab/ci/pipeline/chain/ensure_environments.rb b/lib/gitlab/ci/pipeline/chain/ensure_environments.rb
index 424e1d87fb4..245ef32f06b 100644
--- a/lib/gitlab/ci/pipeline/chain/ensure_environments.rb
+++ b/lib/gitlab/ci/pipeline/chain/ensure_environments.rb
@@ -6,8 +6,6 @@ module Gitlab
module Chain
class EnsureEnvironments < Chain::Base
def perform!
- return unless pipeline.create_deployment_in_separate_transaction?
-
pipeline.stages.map(&:statuses).flatten.each(&method(:ensure_environment))
end
diff --git a/lib/gitlab/ci/pipeline/chain/ensure_resource_groups.rb b/lib/gitlab/ci/pipeline/chain/ensure_resource_groups.rb
index f4e5e6e467a..8e60cafb65b 100644
--- a/lib/gitlab/ci/pipeline/chain/ensure_resource_groups.rb
+++ b/lib/gitlab/ci/pipeline/chain/ensure_resource_groups.rb
@@ -6,8 +6,6 @@ module Gitlab
module Chain
class EnsureResourceGroups < Chain::Base
def perform!
- return unless pipeline.create_deployment_in_separate_transaction?
-
pipeline.stages.map(&:statuses).flatten.each(&method(:ensure_resource_group))
end
diff --git a/lib/gitlab/ci/pipeline/seed/build.rb b/lib/gitlab/ci/pipeline/seed/build.rb
index 5a0ad695741..901208f325a 100644
--- a/lib/gitlab/ci/pipeline/seed/build.rb
+++ b/lib/gitlab/ci/pipeline/seed/build.rb
@@ -79,9 +79,7 @@ module Gitlab
def to_resource
strong_memoize(:resource) do
- processable = initialize_processable
- assign_resource_group(processable) unless @pipeline.create_deployment_in_separate_transaction?
- processable
+ initialize_processable
end
end
@@ -89,39 +87,10 @@ module Gitlab
if bridge?
::Ci::Bridge.new(attributes)
else
- ::Ci::Build.new(attributes).tap do |build|
- unless @pipeline.create_deployment_in_separate_transaction?
- build.assign_attributes(self.class.deployment_attributes_for(build))
- end
- end
+ ::Ci::Build.new(attributes)
end
end
- def assign_resource_group(processable)
- processable.resource_group =
- Seed::Processable::ResourceGroup.new(processable, @resource_group_key)
- .to_resource
- end
-
- def self.deployment_attributes_for(build, environment = nil)
- return {} unless build.has_environment?
-
- environment = Seed::Environment.new(build).to_resource if environment.nil?
-
- unless environment.persisted?
- return { status: :failed, failure_reason: :environment_creation_failure }
- end
-
- build.persisted_environment = environment
-
- {
- deployment: Seed::Deployment.new(build, environment).to_resource,
- metadata_attributes: {
- expanded_environment_name: environment.name
- }
- }
- end
-
private
delegate :logger, to: :@context
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 86a969f9a69..14d75dbeff1 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -17799,6 +17799,9 @@ msgstr ""
msgid "I forgot my password"
msgstr ""
+msgid "I understand the responsibilities involved with managing service account keys"
+msgstr ""
+
msgid "I want to explore GitLab to see if it’s worth switching to"
msgstr ""
@@ -27223,9 +27226,6 @@ msgstr ""
msgid "Profiles|Clear status"
msgstr ""
-msgid "Profiles|Click on icon to activate signin with one of the following services"
-msgstr ""
-
msgid "Profiles|Commit email"
msgstr ""
@@ -27403,6 +27403,9 @@ msgstr ""
msgid "Profiles|Remove avatar"
msgstr ""
+msgid "Profiles|Select a service to sign in with."
+msgstr ""
+
msgid "Profiles|Set new profile picture"
msgstr ""
diff --git a/spec/features/issues/user_sorts_issues_spec.rb b/spec/features/issues/user_sorts_issues_spec.rb
index 48297e9049e..00fdea69b60 100644
--- a/spec/features/issues/user_sorts_issues_spec.rb
+++ b/spec/features/issues/user_sorts_issues_spec.rb
@@ -141,7 +141,7 @@ RSpec.describe "User sorts issues" do
page.within '.issues-list' do
expect(page).to have_content('foo')
expect(page).to have_content('bar')
- expect(page).to have_content('baz')
+ expect(page).not_to have_content('baz')
end
end
diff --git a/spec/finders/issues_finder_spec.rb b/spec/finders/issues_finder_spec.rb
index 31563a6326d..c22e56c3b9e 100644
--- a/spec/finders/issues_finder_spec.rb
+++ b/spec/finders/issues_finder_spec.rb
@@ -1018,6 +1018,8 @@ RSpec.describe IssuesFinder do
end
context 'filtering by due date' do
+ let_it_be(:issue_due_today) { create(:issue, project: project1, due_date: Date.current) }
+ let_it_be(:issue_due_tomorrow) { create(:issue, project: project1, due_date: 1.day.from_now) }
let_it_be(:issue_overdue) { create(:issue, project: project1, due_date: 2.days.ago) }
let_it_be(:issue_due_soon) { create(:issue, project: project1, due_date: 2.days.from_now) }
@@ -1032,6 +1034,30 @@ RSpec.describe IssuesFinder do
end
end
+ context 'with param set to any due date' do
+ let(:params) { base_params.merge(due_date: Issue::AnyDueDate.name) }
+
+ it 'returns issues with any due date' do
+ expect(issues).to contain_exactly(issue_due_today, issue_due_tomorrow, issue_overdue, issue_due_soon)
+ end
+ end
+
+ context 'with param set to due today' do
+ let(:params) { base_params.merge(due_date: Issue::DueToday.name) }
+
+ it 'returns issues due today' do
+ expect(issues).to contain_exactly(issue_due_today)
+ end
+ end
+
+ context 'with param set to due tomorrow' do
+ let(:params) { base_params.merge(due_date: Issue::DueTomorrow.name) }
+
+ it 'returns issues due today' do
+ expect(issues).to contain_exactly(issue_due_tomorrow)
+ end
+ end
+
context 'with param set to overdue' do
let(:params) { base_params.merge(due_date: Issue::Overdue.name) }
@@ -1043,8 +1069,8 @@ RSpec.describe IssuesFinder do
context 'with param set to next month and previous two weeks' do
let(:params) { base_params.merge(due_date: Issue::DueNextMonthAndPreviousTwoWeeks.name) }
- it 'returns issues from the previous two weeks and next month' do
- expect(issues).to contain_exactly(issue_overdue, issue_due_soon)
+ it 'returns issues due in the previous two weeks and next month' do
+ expect(issues).to contain_exactly(issue_due_today, issue_due_tomorrow, issue_overdue, issue_due_soon)
end
end
diff --git a/spec/frontend/environments/deployment_spec.js b/spec/frontend/environments/deployment_spec.js
index a68e17fe6ac..a1b232d783e 100644
--- a/spec/frontend/environments/deployment_spec.js
+++ b/spec/frontend/environments/deployment_spec.js
@@ -1,11 +1,15 @@
import { mountExtended } from 'helpers/vue_test_utils_helper';
import { __, s__ } from '~/locale';
+import { formatDate } from '~/lib/utils/datetime_utility';
+import { useFakeDate } from 'helpers/fake_date';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import Deployment from '~/environments/components/deployment.vue';
import DeploymentStatusBadge from '~/environments/components/deployment_status_badge.vue';
import { resolvedEnvironment } from './graphql/mock_data';
describe('~/environments/components/deployment.vue', () => {
+ useFakeDate(2022, 0, 8, 16);
+
const deployment = resolvedEnvironment.lastDeployment;
let wrapper;
@@ -125,4 +129,23 @@ describe('~/environments/components/deployment.vue', () => {
});
});
});
+
+ describe('created at time', () => {
+ describe('is present', () => {
+ it('shows the timestamp the deployment was deployed at', () => {
+ wrapper = createWrapper();
+ const date = wrapper.findByTitle(formatDate(deployment.createdAt));
+
+ expect(date.text()).toBe('1 day ago');
+ });
+ });
+ describe('is not present', () => {
+ it('does not show the timestamp', () => {
+ wrapper = createWrapper({ propsData: { deployment: { createdAt: null } } });
+ const date = wrapper.findByTitle(formatDate(deployment.createdAt));
+
+ expect(date.exists()).toBe(false);
+ });
+ });
+ });
});
diff --git a/spec/frontend/google_cloud/components/service_accounts_form_spec.js b/spec/frontend/google_cloud/components/service_accounts_form_spec.js
index 5394d0cdaef..7262e12c84d 100644
--- a/spec/frontend/google_cloud/components/service_accounts_form_spec.js
+++ b/spec/frontend/google_cloud/components/service_accounts_form_spec.js
@@ -1,5 +1,5 @@
import { shallowMount } from '@vue/test-utils';
-import { GlButton, GlFormGroup, GlFormSelect } from '@gitlab/ui';
+import { GlButton, GlFormGroup, GlFormSelect, GlFormCheckbox } from '@gitlab/ui';
import ServiceAccountsForm from '~/google_cloud/components/service_accounts_form.vue';
describe('ServiceAccountsForm component', () => {
@@ -9,11 +9,12 @@ describe('ServiceAccountsForm component', () => {
const findAllFormGroups = () => wrapper.findAllComponents(GlFormGroup);
const findAllFormSelects = () => wrapper.findAllComponents(GlFormSelect);
const findAllButtons = () => wrapper.findAllComponents(GlButton);
+ const findCheckbox = () => wrapper.findComponent(GlFormCheckbox);
const propsData = { gcpProjects: [], environments: [], cancelPath: '#cancel-url' };
beforeEach(() => {
- wrapper = shallowMount(ServiceAccountsForm, { propsData });
+ wrapper = shallowMount(ServiceAccountsForm, { propsData, stubs: { GlFormCheckbox } });
});
afterEach(() => {
@@ -35,8 +36,8 @@ describe('ServiceAccountsForm component', () => {
});
it('contains Environments form group', () => {
- const formGorup = findAllFormGroups().at(1);
- expect(formGorup.exists()).toBe(true);
+ const formGroup = findAllFormGroups().at(1);
+ expect(formGroup.exists()).toBe(true);
});
it('contains Environments dropdown', () => {
@@ -56,4 +57,14 @@ describe('ServiceAccountsForm component', () => {
expect(button.text()).toBe(ServiceAccountsForm.i18n.cancelLabel);
expect(button.attributes('href')).toBe('#cancel-url');
});
+
+ it('contains Confirmation checkbox', () => {
+ const checkbox = findCheckbox();
+ expect(checkbox.text()).toBe(ServiceAccountsForm.i18n.checkboxLabel);
+ });
+
+ it('checkbox must be required', () => {
+ const checkbox = findCheckbox();
+ expect(checkbox.attributes('required')).toBe('true');
+ });
});
diff --git a/spec/frontend/lib/utils/number_utility_spec.js b/spec/frontend/lib/utils/number_utility_spec.js
index e743678ea90..dc4aa0ea5ed 100644
--- a/spec/frontend/lib/utils/number_utility_spec.js
+++ b/spec/frontend/lib/utils/number_utility_spec.js
@@ -4,6 +4,7 @@ import {
bytesToMiB,
bytesToGiB,
numberToHumanSize,
+ numberToMetricPrefix,
sum,
isOdd,
median,
@@ -99,6 +100,21 @@ describe('Number Utils', () => {
});
});
+ describe('numberToMetricPrefix', () => {
+ it.each`
+ number | expected
+ ${123} | ${'123'}
+ ${1234} | ${'1.2k'}
+ ${12345} | ${'12.3k'}
+ ${123456} | ${'123.5k'}
+ ${1234567} | ${'1.2m'}
+ ${12345678} | ${'12.3m'}
+ ${123456789} | ${'123.5m'}
+ `('returns $expected given $number', ({ number, expected }) => {
+ expect(numberToMetricPrefix(number)).toBe(expected);
+ });
+ });
+
describe('sum', () => {
it('should add up two values', () => {
expect(sum(1, 2)).toEqual(3);
diff --git a/spec/frontend/sidebar/components/todo_toggle/sidebar_todo_widget_spec.js b/spec/frontend/sidebar/components/todo_toggle/sidebar_todo_widget_spec.js
index 23f1753c4bf..2fef3ab9293 100644
--- a/spec/frontend/sidebar/components/todo_toggle/sidebar_todo_widget_spec.js
+++ b/spec/frontend/sidebar/components/todo_toggle/sidebar_todo_widget_spec.js
@@ -1,4 +1,4 @@
-import { GlIcon } from '@gitlab/ui';
+import { GlIcon, GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
@@ -103,7 +103,7 @@ describe('Sidebar Todo Widget', () => {
});
it('sets default tooltip title', () => {
- expect(wrapper.find(GlIcon).attributes('title')).toBe('Add a to do');
+ expect(wrapper.find(GlButton).attributes('title')).toBe('Add a to do');
});
it('when user has a to do', async () => {
@@ -113,7 +113,7 @@ describe('Sidebar Todo Widget', () => {
await waitForPromises();
expect(wrapper.find(GlIcon).props('name')).toBe('todo-done');
- expect(wrapper.find(GlIcon).attributes('title')).toBe('Mark as done');
+ expect(wrapper.find(GlButton).attributes('title')).toBe('Mark as done');
});
it('emits `todoUpdated` event on click on icon', async () => {
diff --git a/spec/frontend/vue_shared/issuable/list/components/issuable_tabs_spec.js b/spec/frontend/vue_shared/issuable/list/components/issuable_tabs_spec.js
index 5723e2da586..27985895c62 100644
--- a/spec/frontend/vue_shared/issuable/list/components/issuable_tabs_spec.js
+++ b/spec/frontend/vue_shared/issuable/list/components/issuable_tabs_spec.js
@@ -1,5 +1,6 @@
import { GlTab, GlBadge } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
+import { mount, shallowMount } from '@vue/test-utils';
import { setLanguage } from 'helpers/locale_helper';
import IssuableTabs from '~/vue_shared/issuable/list/components/issuable_tabs.vue';
@@ -10,17 +11,18 @@ const createComponent = ({
tabs = mockIssuableListProps.tabs,
tabCounts = mockIssuableListProps.tabCounts,
currentTab = mockIssuableListProps.currentTab,
+ truncateCounts = false,
+ mountFn = shallowMount,
} = {}) =>
- mount(IssuableTabs, {
+ mountFn(IssuableTabs, {
propsData: {
tabs,
tabCounts,
currentTab,
+ truncateCounts,
},
slots: {
- 'nav-actions': `
- <button class="js-new-issuable">New issuable</button>
- `,
+ 'nav-actions': `<button class="js-new-issuable">New issuable</button>`,
},
});
@@ -29,7 +31,6 @@ describe('IssuableTabs', () => {
beforeEach(() => {
setLanguage('en');
- wrapper = createComponent();
});
afterEach(() => {
@@ -40,60 +41,71 @@ describe('IssuableTabs', () => {
const findAllGlBadges = () => wrapper.findAllComponents(GlBadge);
const findAllGlTabs = () => wrapper.findAllComponents(GlTab);
- describe('methods', () => {
- describe('isTabActive', () => {
- it.each`
- tabName | currentTab | returnValue
- ${'opened'} | ${'opened'} | ${true}
- ${'opened'} | ${'closed'} | ${false}
- `(
- 'returns $returnValue when tab name is "$tabName" is current tab is "$currentTab"',
- async ({ tabName, currentTab, returnValue }) => {
- wrapper.setProps({
- currentTab,
- });
-
- await wrapper.vm.$nextTick();
-
- expect(wrapper.vm.isTabActive(tabName)).toBe(returnValue);
- },
- );
- });
+ describe('tabs', () => {
+ it.each`
+ currentTab | returnValue
+ ${'opened'} | ${'true'}
+ ${'closed'} | ${undefined}
+ `(
+ 'when "$currentTab" is the selected tab, the Open tab is active=$returnValue',
+ ({ currentTab, returnValue }) => {
+ wrapper = createComponent({ currentTab });
+
+ const openTab = findAllGlTabs().at(0);
+
+ expect(openTab.attributes('active')).toBe(returnValue);
+ },
+ );
});
describe('template', () => {
it('renders gl-tab for each tab within `tabs` array', () => {
- const tabsEl = findAllGlTabs();
+ wrapper = createComponent();
+
+ const tabs = findAllGlTabs();
- expect(tabsEl.exists()).toBe(true);
- expect(tabsEl).toHaveLength(mockIssuableListProps.tabs.length);
+ expect(tabs).toHaveLength(mockIssuableListProps.tabs.length);
});
- it('renders gl-badge component within a tab', () => {
+ it('renders gl-badge component within a tab', async () => {
+ wrapper = createComponent({ mountFn: mount });
+ await nextTick();
+
const badges = findAllGlBadges();
// Does not render `All` badge since it has an undefined count
expect(badges).toHaveLength(2);
- expect(badges.at(0).text()).toBe('5,000');
+ expect(badges.at(0).text()).toBe('5,678');
expect(badges.at(1).text()).toBe(`${mockIssuableListProps.tabCounts.closed}`);
});
it('renders contents for slot "nav-actions"', () => {
- const buttonEl = wrapper.find('button.js-new-issuable');
+ wrapper = createComponent();
- expect(buttonEl.exists()).toBe(true);
- expect(buttonEl.text()).toBe('New issuable');
+ const button = wrapper.find('button.js-new-issuable');
+
+ expect(button.text()).toBe('New issuable');
+ });
+ });
+
+ describe('counts', () => {
+ it('can display as truncated', async () => {
+ wrapper = createComponent({ truncateCounts: true, mountFn: mount });
+ await nextTick();
+
+ expect(findAllGlBadges().at(0).text()).toBe('5.7k');
});
});
describe('events', () => {
it('gl-tab component emits `click` event on `click` event', () => {
- const tabEl = findAllGlTabs().at(0);
+ wrapper = createComponent();
+
+ const openTab = findAllGlTabs().at(0);
- tabEl.vm.$emit('click', 'opened');
+ openTab.vm.$emit('click', 'opened');
- expect(wrapper.emitted('click')).toBeTruthy();
- expect(wrapper.emitted('click')[0]).toEqual(['opened']);
+ expect(wrapper.emitted('click')).toEqual([['opened']]);
});
});
});
diff --git a/spec/frontend/vue_shared/issuable/list/mock_data.js b/spec/frontend/vue_shared/issuable/list/mock_data.js
index cfc7937b412..8640f4a2cd5 100644
--- a/spec/frontend/vue_shared/issuable/list/mock_data.js
+++ b/spec/frontend/vue_shared/issuable/list/mock_data.js
@@ -133,7 +133,7 @@ export const mockTabs = [
];
export const mockTabCounts = {
- opened: 5000,
+ opened: 5678,
closed: 0,
all: undefined,
};
diff --git a/spec/graphql/types/ci/runner_type_spec.rb b/spec/graphql/types/ci/runner_type_spec.rb
index 1d8d3dd88bb..3f89058f44a 100644
--- a/spec/graphql/types/ci/runner_type_spec.rb
+++ b/spec/graphql/types/ci/runner_type_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe GitlabSchema.types['CiRunner'] do
id description created_at contacted_at maximum_timeout access_level active status
version short_sha revision locked run_untagged ip_address runner_type tag_list
project_count job_count admin_url edit_admin_url user_permissions executor_name
- groups
+ groups projects
]
expect(described_class).to include_graphql_fields(*expected_fields)
diff --git a/spec/lib/bitbucket_server/representation/repo_spec.rb b/spec/lib/bitbucket_server/representation/repo_spec.rb
index 7a773f47ca5..5de4360bbd0 100644
--- a/spec/lib/bitbucket_server/representation/repo_spec.rb
+++ b/spec/lib/bitbucket_server/representation/repo_spec.rb
@@ -9,6 +9,7 @@ RSpec.describe BitbucketServer::Representation::Repo do
"slug": "rouge",
"id": 1,
"name": "rouge",
+ "description": "Rogue Repo",
"scmId": "git",
"state": "AVAILABLE",
"statusMessage": "Available",
@@ -17,7 +18,7 @@ RSpec.describe BitbucketServer::Representation::Repo do
"key": "TEST",
"id": 1,
"name": "test",
- "description": "Test",
+ "description": "Test Project",
"public": false,
"type": "NORMAL",
"links": {
@@ -73,7 +74,7 @@ RSpec.describe BitbucketServer::Representation::Repo do
end
describe '#description' do
- it { expect(subject.description).to eq('Test') }
+ it { expect(subject.description).to eq('Rogue Repo') }
end
describe '#full_name' do
diff --git a/spec/lib/gitlab/ci/pipeline/chain/create_deployments_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/create_deployments_spec.rb
index 0a592395c3a..375841ce236 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/create_deployments_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/create_deployments_spec.rb
@@ -47,18 +47,6 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::CreateDeployments do
expect(job.deployment).to be_nil
end
end
-
- context 'when create_deployment_in_separate_transaction feature flag is disabled' do
- before do
- stub_feature_flags(create_deployment_in_separate_transaction: false)
- end
-
- it 'does not create a deployment record' do
- expect { subject }.not_to change { Deployment.count }
-
- expect(job.deployment).to be_nil
- end
- end
end
context 'when a pipeline contains a teardown job' do
diff --git a/spec/lib/gitlab/ci/pipeline/chain/ensure_environments_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/ensure_environments_spec.rb
index 253928e1a19..6a7d9b58a05 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/ensure_environments_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/ensure_environments_spec.rb
@@ -57,18 +57,6 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::EnsureEnvironments do
expect(job.persisted_environment).to be_nil
end
end
-
- context 'when create_deployment_in_separate_transaction feature flag is disabled' do
- before do
- stub_feature_flags(create_deployment_in_separate_transaction: false)
- end
-
- it 'does not create any environments' do
- expect { subject }.not_to change { Environment.count }
-
- expect(job.persisted_environment).to be_nil
- end
- end
end
context 'when a pipeline contains a teardown job' do
diff --git a/spec/lib/gitlab/ci/pipeline/chain/ensure_resource_groups_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/ensure_resource_groups_spec.rb
index 87df5a3e21b..571455d6279 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/ensure_resource_groups_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/ensure_resource_groups_spec.rb
@@ -60,18 +60,6 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::EnsureResourceGroups do
expect(job.resource_group).to be_nil
end
end
-
- context 'when create_deployment_in_separate_transaction feature flag is disabled' do
- before do
- stub_feature_flags(create_deployment_in_separate_transaction: false)
- end
-
- it 'does not create any resource groups' do
- expect { subject }.not_to change { Ci::ResourceGroup.count }
-
- expect(job.resource_group).to be_nil
- end
- end
end
context 'when a pipeline does not contain a job that requires a resource group' do
diff --git a/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb b/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
index 2f9fcd7caac..49505d397c2 100644
--- a/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
@@ -411,171 +411,6 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
describe '#to_resource' do
subject { seed_build.to_resource }
- before do
- stub_feature_flags(create_deployment_in_separate_transaction: false)
- end
-
- context 'when job is Ci::Build' do
- it { is_expected.to be_a(::Ci::Build) }
- it { is_expected.to be_valid }
-
- shared_examples_for 'deployment job' do
- it 'returns a job with deployment' do
- expect { subject }.to change { Environment.count }.by(1)
-
- expect(subject.deployment).not_to be_nil
- expect(subject.deployment.deployable).to eq(subject)
- expect(subject.deployment.environment.name).to eq(expected_environment_name)
- end
- end
-
- shared_examples_for 'non-deployment job' do
- it 'returns a job without deployment' do
- expect(subject.deployment).to be_nil
- end
- end
-
- shared_examples_for 'ensures environment existence' do
- it 'has environment' do
- expect { subject }.to change { Environment.count }.by(1)
-
- expect(subject).to be_has_environment
- expect(subject.environment).to eq(environment_name)
- expect(subject.metadata.expanded_environment_name).to eq(expected_environment_name)
- expect(Environment.exists?(name: expected_environment_name)).to eq(true)
- end
- end
-
- shared_examples_for 'ensures environment inexistence' do
- it 'does not have environment' do
- expect { subject }.not_to change { Environment.count }
-
- expect(subject).not_to be_has_environment
- expect(subject.environment).to be_nil
- expect(subject.metadata&.expanded_environment_name).to be_nil
- expect(Environment.exists?(name: expected_environment_name)).to eq(false)
- end
- end
-
- context 'when job deploys to production' do
- let(:environment_name) { 'production' }
- let(:expected_environment_name) { 'production' }
- let(:attributes) { { name: 'deploy', ref: 'master', environment: 'production' } }
-
- it_behaves_like 'deployment job'
- it_behaves_like 'ensures environment existence'
-
- context 'when create_deployment_in_separate_transaction feature flag is enabled' do
- before do
- stub_feature_flags(create_deployment_in_separate_transaction: true)
- end
-
- it 'does not create any deployments nor environments' do
- expect(subject.deployment).to be_nil
- expect(Environment.count).to eq(0)
- expect(Deployment.count).to eq(0)
- end
- end
-
- context 'when the environment name is invalid' do
- let(:attributes) { { name: 'deploy', ref: 'master', environment: '!!!' } }
-
- it 'fails the job with a failure reason and does not create an environment' do
- expect(subject).to be_failed
- expect(subject).to be_environment_creation_failure
- expect(subject.metadata.expanded_environment_name).to be_nil
- expect(Environment.exists?(name: expected_environment_name)).to eq(false)
- end
- end
- end
-
- context 'when job starts a review app' do
- let(:environment_name) { 'review/$CI_COMMIT_REF_NAME' }
- let(:expected_environment_name) { "review/#{pipeline.ref}" }
-
- let(:attributes) do
- {
- name: 'deploy', ref: 'master', environment: environment_name,
- options: { environment: { name: environment_name } }
- }
- end
-
- it_behaves_like 'deployment job'
- it_behaves_like 'ensures environment existence'
- end
-
- context 'when job stops a review app' do
- let(:environment_name) { 'review/$CI_COMMIT_REF_NAME' }
- let(:expected_environment_name) { "review/#{pipeline.ref}" }
-
- let(:attributes) do
- {
- name: 'deploy', ref: 'master', environment: environment_name,
- options: { environment: { name: environment_name, action: 'stop' } }
- }
- end
-
- it 'returns a job without deployment' do
- expect(subject.deployment).to be_nil
- end
-
- it_behaves_like 'non-deployment job'
- it_behaves_like 'ensures environment existence'
- end
-
- context 'when job belongs to a resource group' do
- let(:resource_group) { 'iOS' }
- let(:attributes) { { name: 'rspec', ref: 'master', resource_group_key: resource_group, environment: 'production' }}
-
- it 'returns a job with resource group' do
- expect(subject.resource_group).not_to be_nil
- expect(subject.resource_group.key).to eq('iOS')
- expect(Ci::ResourceGroup.count).to eq(1)
- end
-
- context 'when create_deployment_in_separate_transaction feature flag is enabled' do
- before do
- stub_feature_flags(create_deployment_in_separate_transaction: true)
- end
-
- it 'does not create any resource groups' do
- expect(subject.resource_group).to be_nil
- expect(Ci::ResourceGroup.count).to eq(0)
- end
- end
-
- context 'when resource group has $CI_ENVIRONMENT_NAME in it' do
- let(:resource_group) { 'test/$CI_ENVIRONMENT_NAME' }
-
- it 'expands environment name' do
- expect(subject.resource_group.key).to eq('test/production')
- end
- end
- end
- end
-
- context 'when job is a bridge' do
- let(:base_attributes) do
- {
- name: 'rspec', ref: 'master', options: { trigger: 'my/project' }, scheduling_type: :stage
- }
- end
-
- let(:attributes) { base_attributes }
-
- it { is_expected.to be_a(::Ci::Bridge) }
- it { is_expected.to be_valid }
-
- context 'when job belongs to a resource group' do
- let(:attributes) { base_attributes.merge(resource_group_key: 'iOS') }
-
- it 'returns a job with resource group' do
- expect(subject.resource_group).not_to be_nil
- expect(subject.resource_group.key).to eq('iOS')
- end
- end
- end
-
it 'memoizes a resource object' do
expect(subject.object_id).to eq seed_build.to_resource.object_id
end
diff --git a/spec/models/container_repository_spec.rb b/spec/models/container_repository_spec.rb
index 8f7c13d7ae6..6cfd7def013 100644
--- a/spec/models/container_repository_spec.rb
+++ b/spec/models/container_repository_spec.rb
@@ -330,6 +330,52 @@ RSpec.describe ContainerRepository do
end
end
+ describe '.find_by_path' do
+ let_it_be(:container_repository) { create(:container_repository) }
+ let_it_be(:repository_path) { container_repository.project.full_path }
+
+ let(:path) { ContainerRegistry::Path.new(repository_path + '/' + container_repository.name) }
+
+ subject { described_class.find_by_path(path) }
+
+ context 'when repository exists' do
+ it 'finds the repository' do
+ expect(subject).to eq(container_repository)
+ end
+ end
+
+ context 'when repository does not exist' do
+ let(:path) { ContainerRegistry::Path.new(repository_path + '/some/image') }
+
+ it 'returns nil' do
+ expect(subject).to be_nil
+ end
+ end
+ end
+
+ describe '.find_by_path!' do
+ let_it_be(:container_repository) { create(:container_repository) }
+ let_it_be(:repository_path) { container_repository.project.full_path }
+
+ let(:path) { ContainerRegistry::Path.new(repository_path + '/' + container_repository.name) }
+
+ subject { described_class.find_by_path!(path) }
+
+ context 'when repository exists' do
+ it 'finds the repository' do
+ expect(subject).to eq(container_repository)
+ end
+ end
+
+ context 'when repository does not exist' do
+ let(:path) { ContainerRegistry::Path.new(repository_path + '/some/image') }
+
+ it 'raises an exception' do
+ expect { subject }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+ end
+ end
+
describe '.build_root_repository' do
let(:repository) do
described_class.build_root_repository(project)
@@ -458,6 +504,24 @@ RSpec.describe ContainerRepository do
it { is_expected.to eq([repository]) }
end
+ describe '#migration_importing?' do
+ let_it_be_with_reload(:container_repository) { create(:container_repository, migration_state: 'importing')}
+
+ subject { container_repository.migration_importing? }
+
+ it { is_expected.to eq(true) }
+
+ context 'when not importing' do
+ before do
+ # Technical debt: when the state machine is added, we should iterate through all possible states
+ # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78499
+ container_repository.update_column(:migration_state, 'default')
+ end
+
+ it { is_expected.to eq(false) }
+ end
+ end
+
context 'with repositories' do
let_it_be_with_reload(:repository) { create(:container_repository, :cleanup_unscheduled) }
let_it_be(:other_repository) { create(:container_repository, :cleanup_unscheduled) }
diff --git a/spec/requests/api/graphql/ci/runner_spec.rb b/spec/requests/api/graphql/ci/runner_spec.rb
index 61f11952ddc..eb1f84e3ef9 100644
--- a/spec/requests/api/graphql/ci/runner_spec.rb
+++ b/spec/requests/api/graphql/ci/runner_spec.rb
@@ -25,6 +25,8 @@ RSpec.describe 'Query.runner(id)' do
access_level: 0, tag_list: %w[tag1 tag2], run_untagged: true, executor_type: :shell)
end
+ let_it_be(:active_project_runner) { create(:ci_runner, :project) }
+
def get_runner(id)
case id
when :active_instance_runner
@@ -33,6 +35,8 @@ RSpec.describe 'Query.runner(id)' do
inactive_instance_runner
when :active_group_runner
active_group_runner
+ when :active_project_runner
+ active_project_runner
end
end
@@ -55,7 +59,7 @@ RSpec.describe 'Query.runner(id)' do
runner = get_runner(runner_id)
expect(runner_data).to match a_hash_including(
- 'id' => "gid://gitlab/Ci::Runner/#{runner.id}",
+ 'id' => runner.to_global_id.to_s,
'description' => runner.description,
'createdAt' => runner.created_at&.iso8601,
'contactedAt' => runner.contacted_at&.iso8601,
@@ -103,7 +107,7 @@ RSpec.describe 'Query.runner(id)' do
runner = get_runner(runner_id)
expect(runner_data).to match a_hash_including(
- 'id' => "gid://gitlab/Ci::Runner/#{runner.id}",
+ 'id' => runner.to_global_id.to_s,
'adminUrl' => nil
)
expect(runner_data['tagList']).to match_array runner.tag_list
@@ -179,7 +183,7 @@ RSpec.describe 'Query.runner(id)' do
runner_data = graphql_data_at(:runner)
expect(runner_data).to match a_hash_including(
- 'id' => "gid://gitlab/Ci::Runner/#{project_runner.id}",
+ 'id' => project_runner.to_global_id.to_s,
'locked' => is_locked
)
end
@@ -216,7 +220,7 @@ RSpec.describe 'Query.runner(id)' do
a_hash_including(
'webUrl' => "http://localhost/groups/#{group.full_path}/-/runners/#{active_group_runner.id}",
'node' => {
- 'id' => "gid://gitlab/Ci::Runner/#{active_group_runner.id}"
+ 'id' => active_group_runner.to_global_id.to_s
}
)
]
@@ -227,7 +231,7 @@ RSpec.describe 'Query.runner(id)' do
let(:query) do
%(
query {
- runner(id: "gid://gitlab/Ci::Runner/#{active_group_runner.id}") {
+ runner(id: "#{active_group_runner.to_global_id}") {
groups {
nodes {
id
@@ -302,21 +306,36 @@ RSpec.describe 'Query.runner(id)' do
let!(:job) { create(:ci_build, runner: project_runner1) }
- context 'requesting project and job counts' do
+ context 'requesting projects and counts for projects and jobs' do
let(:query) do
%(
query {
projectRunner1: runner(id: "#{project_runner1.to_global_id}") {
projectCount
jobCount
+ projects {
+ nodes {
+ id
+ }
+ }
}
projectRunner2: runner(id: "#{project_runner2.to_global_id}") {
projectCount
jobCount
+ projects {
+ nodes {
+ id
+ }
+ }
}
activeInstanceRunner: runner(id: "#{active_instance_runner.to_global_id}") {
projectCount
jobCount
+ projects {
+ nodes {
+ id
+ }
+ }
}
}
)
@@ -335,13 +354,23 @@ RSpec.describe 'Query.runner(id)' do
expect(runner1_data).to match a_hash_including(
'jobCount' => 1,
- 'projectCount' => 2)
+ 'projectCount' => 2,
+ 'projects' => {
+ 'nodes' => [
+ { 'id' => project1.to_global_id.to_s },
+ { 'id' => project2.to_global_id.to_s }
+ ]
+ })
expect(runner2_data).to match a_hash_including(
'jobCount' => 0,
- 'projectCount' => 0)
+ 'projectCount' => 0,
+ 'projects' => {
+ 'nodes' => []
+ })
expect(runner3_data).to match a_hash_including(
'jobCount' => 0,
- 'projectCount' => nil)
+ 'projectCount' => nil,
+ 'projects' => nil)
end
end
end
@@ -356,6 +385,10 @@ RSpec.describe 'Query.runner(id)' do
context 'on group runner' do
it_behaves_like 'retrieval by unauthorized user', :active_group_runner
end
+
+ context 'on project runner' do
+ it_behaves_like 'retrieval by unauthorized user', :active_project_runner
+ end
end
describe 'by non-admin user' do
diff --git a/spec/requests/api/issues/issues_spec.rb b/spec/requests/api/issues/issues_spec.rb
index 9204ee4d7f0..e15f847d866 100644
--- a/spec/requests/api/issues/issues_spec.rb
+++ b/spec/requests/api/issues/issues_spec.rb
@@ -488,6 +488,8 @@ RSpec.describe API::Issues do
let_it_be(:issue3) { create(:issue, project: project, author: user, due_date: frozen_time + 10.days) }
let_it_be(:issue4) { create(:issue, project: project, author: user, due_date: frozen_time + 34.days) }
let_it_be(:issue5) { create(:issue, project: project, author: user, due_date: frozen_time - 8.days) }
+ let_it_be(:issue6) { create(:issue, project: project, author: user, due_date: frozen_time) }
+ let_it_be(:issue7) { create(:issue, project: project, author: user, due_date: frozen_time + 1.day) }
before do
travel_to(frozen_time)
@@ -500,7 +502,13 @@ RSpec.describe API::Issues do
it 'returns them all when argument is empty' do
get api('/issues?due_date=', user)
- expect_paginated_array_response(issue5.id, issue4.id, issue3.id, issue2.id, issue.id, closed_issue.id)
+ expect_paginated_array_response(issue7.id, issue6.id, issue5.id, issue4.id, issue3.id, issue2.id, issue.id, closed_issue.id)
+ end
+
+ it 'returns issues with due date' do
+ get api('/issues?due_date=any', user)
+
+ expect_paginated_array_response(issue7.id, issue6.id, issue5.id, issue4.id, issue3.id, issue2.id)
end
it 'returns issues without due date' do
@@ -512,19 +520,31 @@ RSpec.describe API::Issues do
it 'returns issues due for this week' do
get api('/issues?due_date=week', user)
- expect_paginated_array_response(issue2.id)
+ expect_paginated_array_response(issue7.id, issue6.id, issue2.id)
end
it 'returns issues due for this month' do
get api('/issues?due_date=month', user)
- expect_paginated_array_response(issue3.id, issue2.id)
+ expect_paginated_array_response(issue7.id, issue6.id, issue3.id, issue2.id)
end
it 'returns issues that are due previous two weeks and next month' do
get api('/issues?due_date=next_month_and_previous_two_weeks', user)
- expect_paginated_array_response(issue5.id, issue4.id, issue3.id, issue2.id)
+ expect_paginated_array_response(issue7.id, issue6.id, issue5.id, issue4.id, issue3.id, issue2.id)
+ end
+
+ it 'returns issues that are due today' do
+ get api('/issues?due_date=today', user)
+
+ expect_paginated_array_response(issue6.id)
+ end
+
+ it 'returns issues that are due tomorrow' do
+ get api('/issues?due_date=tomorrow', user)
+
+ expect_paginated_array_response(issue7.id)
end
it 'returns issues that are overdue' do
diff --git a/spec/services/ci/retry_build_service_spec.rb b/spec/services/ci/retry_build_service_spec.rb
index 4e8e41ca6e6..0f24883bd7b 100644
--- a/spec/services/ci/retry_build_service_spec.rb
+++ b/spec/services/ci/retry_build_service_spec.rb
@@ -370,23 +370,6 @@ RSpec.describe Ci::RetryBuildService do
it_behaves_like 'when build with deployment is retried'
it_behaves_like 'when build with dynamic environment is retried'
- context 'when create_deployment_in_separate_transaction feature flag is disabled' do
- let(:new_build) do
- travel_to(1.second.from_now) do
- ::Gitlab::Database::QueryAnalyzers::PreventCrossDatabaseModification.allow_cross_database_modification_within_transaction(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/345668') do
- service.clone!(build)
- end
- end
- end
-
- before do
- stub_feature_flags(create_deployment_in_separate_transaction: false)
- end
-
- it_behaves_like 'when build with deployment is retried'
- it_behaves_like 'when build with dynamic environment is retried'
- end
-
context 'when build has needs' do
before do
create(:ci_build_need, build: build, name: 'build1')
diff --git a/spec/support/shared_examples/services/container_registry_auth_service_shared_examples.rb b/spec/support/shared_examples/services/container_registry_auth_service_shared_examples.rb
index 87bf134eeb8..4713e2fc789 100644
--- a/spec/support/shared_examples/services/container_registry_auth_service_shared_examples.rb
+++ b/spec/support/shared_examples/services/container_registry_auth_service_shared_examples.rb
@@ -167,7 +167,7 @@ RSpec.shared_examples 'a container registry auth service' do
stub_feature_flags(container_registry_cdn_redirect: false)
end
- describe '#full_access_token' do
+ describe '.full_access_token' do
let_it_be(:project) { create(:project) }
let(:token) { described_class.full_access_token(project.full_path) }
@@ -181,7 +181,21 @@ RSpec.shared_examples 'a container registry auth service' do
it_behaves_like 'not a container repository factory'
end
- describe '#pull_access_token' do
+ describe '.import_access_token' do
+ let_it_be(:project) { create(:project) }
+
+ let(:token) { described_class.import_access_token(project.full_path) }
+
+ subject { { token: token } }
+
+ it_behaves_like 'an accessible' do
+ let(:actions) { ['import'] }
+ end
+
+ it_behaves_like 'not a container repository factory'
+ end
+
+ describe '.pull_access_token' do
let_it_be(:project) { create(:project) }
let(:token) { described_class.pull_access_token(project.full_path) }
@@ -1126,4 +1140,72 @@ RSpec.shared_examples 'a container registry auth service' do
end
end
end
+
+ context 'when importing' do
+ let_it_be(:container_repository) { create(:container_repository, :root, migration_state: 'importing') }
+ let_it_be(:current_project) { container_repository.project }
+ let_it_be(:current_user) { create(:user) }
+
+ before do
+ current_project.add_developer(current_user)
+ end
+
+ shared_examples 'containing the import error' do
+ it 'includes a helpful error message' do
+ expect(subject[:errors].first).to include(message: /Your repository is currently being migrated/)
+ end
+ end
+
+ context 'push request' do
+ let(:current_params) do
+ { scopes: ["repository:#{container_repository.path}:push"] }
+ end
+
+ it_behaves_like 'a forbidden' do
+ it_behaves_like 'containing the import error'
+ end
+ end
+
+ context 'delete request' do
+ let(:current_params) do
+ { scopes: ["repository:#{container_repository.path}:delete"] }
+ end
+
+ it_behaves_like 'a forbidden' do
+ it_behaves_like 'containing the import error'
+ end
+ end
+
+ context '* request' do
+ let(:current_params) do
+ { scopes: ["repository:#{container_repository.path}:*"] }
+ end
+
+ it_behaves_like 'a forbidden' do
+ it_behaves_like 'containing the import error'
+ end
+ end
+
+ context 'pull request' do
+ let(:current_params) do
+ { scopes: ["repository:#{container_repository.path}:pull"] }
+ end
+
+ let(:project) { current_project }
+
+ it_behaves_like 'a pullable'
+ end
+
+ context 'mixed request' do
+ let(:current_params) do
+ { scopes: ["repository:#{container_repository.path}:pull,push"] }
+ end
+
+ let(:project) { current_project }
+
+ it_behaves_like 'a forbidden' do
+ it_behaves_like 'containing the import error'
+ end
+ end
+ end
end
diff --git a/spec/uploaders/import_export_uploader_spec.rb b/spec/uploaders/import_export_uploader_spec.rb
index cb7a89193e6..64e92f5d60e 100644
--- a/spec/uploaders/import_export_uploader_spec.rb
+++ b/spec/uploaders/import_export_uploader_spec.rb
@@ -10,6 +10,20 @@ RSpec.describe ImportExportUploader do
subject { described_class.new(model, :import_file) }
context 'local store' do
+ describe '#move_to_cache' do
+ it 'returns false' do
+ expect(subject.move_to_cache).to be false
+ end
+
+ context 'with project export' do
+ subject { described_class.new(model, :export_file) }
+
+ it 'returns true' do
+ expect(subject.move_to_cache).to be true
+ end
+ end
+ end
+
describe '#move_to_store' do
it 'returns true' do
expect(subject.move_to_store).to be true
@@ -33,6 +47,20 @@ RSpec.describe ImportExportUploader do
let(:fixture) { File.join('spec', 'fixtures', 'group_export.tar.gz') }
end
+ describe '#move_to_cache' do
+ it 'returns false' do
+ expect(subject.move_to_cache).to be false
+ end
+
+ context 'with project export' do
+ subject { described_class.new(model, :export_file) }
+
+ it 'returns true' do
+ expect(subject.move_to_cache).to be false
+ end
+ end
+ end
+
describe '#move_to_store' do
it 'returns false' do
expect(subject.move_to_store).to be false
diff --git a/spec/workers/concerns/application_worker_spec.rb b/spec/workers/concerns/application_worker_spec.rb
index 85731de2a45..95d9b982fc4 100644
--- a/spec/workers/concerns/application_worker_spec.rb
+++ b/spec/workers/concerns/application_worker_spec.rb
@@ -247,45 +247,6 @@ RSpec.describe ApplicationWorker do
end
end
- describe '.perform_async' do
- using RSpec::Parameterized::TableSyntax
-
- where(:primary_only?, :skip_scheduling_ff, :data_consistency, :schedules_job?) do
- true | false | :sticky | false
- true | false | :delayed | false
- true | false | :always | false
- true | true | :sticky | false
- true | true | :delayed | false
- true | true | :always | false
- false | false | :sticky | true
- false | false | :delayed | true
- false | false | :always | false
- false | true | :sticky | false
- false | true | :delayed | false
- false | true | :always | false
- end
-
- before do
- stub_const(worker.name, worker)
- worker.data_consistency(data_consistency)
-
- allow(Gitlab::Database::LoadBalancing).to receive(:primary_only?).and_return(primary_only?)
- stub_feature_flags(skip_scheduling_workers_for_replicas: skip_scheduling_ff)
- end
-
- with_them do
- it 'schedules or enqueues the job correctly' do
- if schedules_job?
- expect(worker).to receive(:perform_in).with(described_class::DEFAULT_DELAY_INTERVAL.seconds, 123)
- else
- expect(worker).not_to receive(:perform_in)
- end
-
- worker.perform_async(123)
- end
- end
- end
-
context 'different kinds of push_bulk' do
shared_context 'set safe limit beyond the number of jobs to be enqueued' do
before do