Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-01-24 18:14:42 +00:00
parent 87543246d9
commit fdc98c3e3c
77 changed files with 1520 additions and 652 deletions

View file

@ -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

View file

@ -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

View file

@ -1 +1 @@
7b20a6045e8d2a25c86633461c03b13353915643
85efc2a008ed64cf8ed516aa43537712b478e139

View file

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

View file

@ -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>

View file

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

View file

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

View file

@ -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;

View file

@ -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
@ -85,6 +85,27 @@ export function numberToHumanSize(size, digits = 2) {
return sprintf(__('%{size} GiB'), { size: bytesToGiB(size).toFixed(digits) });
}
/**
* 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

View file

@ -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 }}

View file

@ -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>

View file

@ -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>

View file

@ -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);
},
},
};

View file

@ -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?

View file

@ -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

View file

@ -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
groups = Group.where(id: group_ids).index_by(&:id)
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::RunnerNamespace, Group, :runner_groups, :namespace_id)
end
def projects
return unless runner.project_type?
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

View file

@ -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)

View file

@ -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')

View file

@ -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')) }

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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.

View file

@ -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.

View file

@ -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

View file

@ -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. |

View file

@ -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` |

View file

@ -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:

View file

@ -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.

View file

@ -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

View file

@ -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.

View file

@ -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)

View file

@ -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.

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

View file

@ -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/)

View file

@ -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:
Here's a list of things created by the user 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.
- 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

View file

@ -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:

View file

@ -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

View file

@ -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

View file

@ -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.

View file

@ -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
```

View file

@ -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.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

View file

@ -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:

View file

@ -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(', ')}"

View file

@ -30,7 +30,7 @@ module BitbucketServer
end
def description
project['description']
raw['description']
end
def full_name

View file

@ -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?

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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 its 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 ""

View file

@ -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

View file

@ -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

View file

@ -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);
});
});
});
});

View file

@ -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');
});
});

View file

@ -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);

View file

@ -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 () => {

View file

@ -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,
});
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 });
await wrapper.vm.$nextTick();
const openTab = findAllGlTabs().at(0);
expect(wrapper.vm.isTabActive(tabName)).toBe(returnValue);
},
);
});
expect(openTab.attributes('active')).toBe(returnValue);
},
);
});
describe('template', () => {
it('renders gl-tab for each tab within `tabs` array', () => {
const tabsEl = findAllGlTabs();
wrapper = createComponent();
expect(tabsEl.exists()).toBe(true);
expect(tabsEl).toHaveLength(mockIssuableListProps.tabs.length);
const tabs = findAllGlTabs();
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();
tabEl.vm.$emit('click', 'opened');
const openTab = findAllGlTabs().at(0);
expect(wrapper.emitted('click')).toBeTruthy();
expect(wrapper.emitted('click')[0]).toEqual(['opened']);
openTab.vm.$emit('click', 'opened');
expect(wrapper.emitted('click')).toEqual([['opened']]);
});
});
});

View file

@ -133,7 +133,7 @@ export const mockTabs = [
];
export const mockTabCounts = {
opened: 5000,
opened: 5678,
closed: 0,
all: undefined,
};

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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) }

View file

@ -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

View file

@ -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

View file

@ -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')

View file

@ -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

View file

@ -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

View file

@ -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